GoldSim’s core functionality can be extended using custom code provided in a dynamically linked library (DLL). To accomplish this GoldSim provides a very simple function interface definition that must be implemented by and exposed from the DLL. GoldSim is a native application, based on the Win32 platform. The extension interface provided by GoldSim requires the called code to be native. This is necessary because GoldSim itself is native code, entirely written in C++. An example model with source code for the DLL is included at the bottom of this article.
The .NET platform is considered a managed platform (garbage collection). Any code written for the .NET platform is managed code. Code written for the Win32 platform is considered unmanaged code. Managed code cannot be loaded in the process space of an unmanaged application. That is the reason why GoldSim, an unmanaged application, cannot directly link to a .NET DLL (containing managed code).
Fortunately, Microsoft provides a solution for such a problem by allowing Visual C++ to generate mixed-mode DLLs containing code segments of both worlds. In order to extend GoldSim with .NET code written in any language other than Visual C++/CLR one will need to provide two components:
1) A mixed-mode DLL that acts as the middleman between the unmanaged GoldSim and the managed DLL. Such mixing of the managed und unmanaged worlds is only possible in Visual C++/CLR.
2) A .NET DLL containing a user-defined function written in a .NET language. This could be any .NET language, but for this example it is assumed to be C#.
The mixed-mode DLL can be considered as having two halves. One half is unmanaged C++ code, and works just like any unmanaged extension DLL works with GoldSim. The other half is managed C++ code, which provides the ability to call any .NET library functions or load libraries and call functions in .NET DLLs.
The example solution ‘GoldSim C# External’ consists of three projects:
1) The user’s custom function (algorithm) written in C#.
2) The mixed-mode C++ code to provide a bridge between the unmanaged and managed worlds.
3) A C++ console application to mimic the function calls and execution sequence of GoldSim.
Figure 1: Solution tree with projects in Visual Studio 2010.
Project Details: CSharp External DLL is a .NET project written in C# and configured to generate a .NET class library (a DLL):
Source code file Class1.cs declares a namespace and two library functions.
Mixed Mode DLL is a C++ Dynamic Library (.dll) project. Note that the project generates native code; it does not implement Common Language Runtime Support.
Figure 2: General configuration of mixed-mode DLL project.
The bottom half of source code file ManagedWrapper.cli.cpp (from line 66) is standard C/C++ code taken from a GoldSim example. However, the code above it is managed code. To accomplish that the source code file must include Common Language Runtime Support. This can be set in the file’s property dialog:
Figure 3: General C++ properties for ManagedWrapper.cli.cpp file.
The top of the mixed-mode source code includes a #suing directive with a reference to the C# Class Library: #using <CSharp External DLL.dll>
The file also includes a helper class with some functions to ensure the DLL projects can be used in any folder, not just from the GoldSim execution folder. Please see the extensive comments above the declaration of class ManagedDLLHelper and the call to ManagedDLLHelper::PrepareAssembly() at the beginning of the native functions (e.g. MixedSum).
The most important code in the mixed-mode DLL project are the function prototypes calling the C# function exposed from class library CSharp External DLL.dll. As can be seen in the example below, these functions simply call a specific function (CSharpSum) exposed from a class (ClassForGoldSim) declared in a namespace (CSharp_External_DLL):
double ManagedSum(double op1, double op2)
return CSharp_External_DLL::ClassForGoldSim::CSharpSum(op1, op2);
The calls into the C# .NET library have been moved to specific functions to increase code clarity and readability. Of course, in a simple example such as this one the call to the C# .NET library could have been made directly from within the native function. That is instead of this:
outarg = ManagedSum(inarg, inarg);
the following is also possible:
outarg = CSharp_External_DLL::ClassForGoldSim::CSharpSum(inarg, inarg);
The MFC Console App project is for testing only. It is not needed when using the C# .NET library with GoldSim. The purpose of the application is to mimic the function calls and execution sequence used by GoldSim. This is handy to test and debug the library outside of GoldSim. The only source code file of importance is MFC Console App.cpp. The file defines the entry point of the application (_tmain) as well as a helper function with a sequence of calls to load and call the DLL (CallExternalDLLFunction).
In order to build the solution Visual Studio 2010 with support for Visual C++ and Visual C# must be installed. Simply load the solution file and build the solution (F7).
The example folder includes a subfolder containing a GoldSim example model and pre-built release code versions of the mixed-mode DLL and the C# class library DLL.
Open the GoldSim model using GoldSim 11 or higher and run it.
Note that the only the mixed-mode DLL is called directly from GoldSim (using External element ‘MixedSum’). The C# DLL cannot be called from GoldSim. Note, however, that it is good practice to make GoldSim aware of the C# DLL by creating a reference to it using a File element (‘CSharpDLL’). This reference ensures that GoldSim checks for the existence of the ‘CSharp External DLL.dll’ file. Such reference is vital if Distributed Processing is utilized to simulate the GoldSim model over multiple processors or computers.