I am trying to create a cpp dll which will utilize the functions of a managed .net dll. How do I create a reference to the .net dll in my cpp project? The .net dll was created by others. I just have its function references.
I have taken a crack at this using VS2019 and created a C++/CLI project, the end product of which, as I understand it, is a .lib file. A programming language called Easylanguage requires a dll which exports its functions using the __stdcall calling convention. The company (NinjaTrader) whose dll this is used to provide a dll which used the calling convention that Easylanguage (Tradestation) could call directly. Now, it will be a much more complicated communication, if it's even possible. That probably doesn't make much sense, but it's about all I know at this point.
Thanks for doing that. I do recognize much of what is going on, but it is, for the most part, beyond my ken. I am going to turn this project over to a competent developer.
I am trying to work my way through taking the above example and building VS 2019 project(s). The first thing I did was create a project using the ManagedLibrary.cs file. This produced a dll called ClassLibrary3.dll.
Then I started a second project to which I added the files WrapperLibrary.h (header file) and WrapperLibrary.cpp (Source File). I think I need to refer to the dll created in the first project, or should all the files go into one project? If I am to refer to the dll, where/how?
The first thing I did was create a project using the ManagedLibrary.cs file. This produced a dll called ClassLibrary3.dll.
The "managed" library was just an example. Of course, you can create your own example "managed" DLL.
...but you probably want to use your existing "NinjaTrader.Client.dll" instead 😏
I think I need to refer to the dll created in the first project, or should all the files go into one project? If I am to refer to the dll, where/how
The "wrapper" library needs to be a project of its own. It needs to be a C++/CLI project!
And yes, you have to add a reference to the "managed" DLL (e.g. "NinjaTrader.Client.dll") to your "wrapper" library project.
...otherwise your "wrapper" code wouldn't be able to use classes (or call methods) from the "managed" DLL.
To make it clear, you can use one Visual Studio solution, but you need two or three separate projects:
[1] The "managed" library (must be C#/.NET project) – not required (obviously), if you use an existing "managed" DLL
[2] The "wrapper" library (must be C++/CLI project)
[3] The "native" C++ program (must be native C++ project)
My "project" has 3 parts, two of which I already have:
1. NinjaTrader.Client.dll
2. The Wrapper.dll (grass roots project)
3. Tradestation Easylanguage which is capable of calling dll functions that use __stdcall calling convention.
I am very experienced with Easylanguage (by Tradestation) having used it for over 20 years. I know how to use dll functions. I have been doing this up until now because Ninjatrader provided a different dll (NtDirect.dll), which Easylanguage could communicate with. They are discontinuing that on their next platform update and my broker managed trading software that I have developed over many years will be worthless unless I can figure out how to create this wrapper dll. This all has to happen within a couple of weeks. That's my story.
I have programming experience, but I'm not conversant in C++ or C# or VS. I'm trying to teach myself. This was just FYI. I may have more questions as I experiment. I appreciate your help.
When I try to add a reference (my ClassLibrary3.dll) from the first project, I'd expect to be able to browse to its location to reference it, but when I follow the example of the posted image and also the VS instructions, no browse options comes up.
As said before, you have to add your "ClassLibrary3" to the references of "CPPWrapper" project, in order to be able to use any classes (or call any methods) from "ClassLibrary3" inside the "CPPWrapper" code. Also, if you still intend to use "NinjaTrader.Client.dll", then add that as a reference to your "CPPWrapper" project – and get rid of project "ClassLibrary3" altogether. Whatever you prefer... 😀
Also, please make sure that your "CPPWrapper" project was created as project type: CLR Class Library (.NET Framework) [C++].
I have started over on the project. I have added two references, the C# hello example dll that you provided, and the NinjaTrader.Client.dll. The attached snip shows the Cpp code that you provided, and I assume that somewhere in there I need to add a call(?) to one of those referenced dll's. What does that look like? https://imgur.com/a/a8Elonv
Yeah, inside your "wrapper" library you have to call the "managed" library. The exact code, of course, totally depends on what classes/methods of the "managed" library you want to call! So, simply adjust the code inside the "MySayHelloWrapper" function as needed. And, of course, the name of that function is arbitrary; you probably want to choose a more fitting name for what you do 😏
Note: In my example, the System::String that comes from the "managed" library was converted into a "native" C string (wchar_t* pointer), via Marshal::StringToHGlobalUni(), so that we can return it to the "native" C/C++ application. But, the string buffer must be de-allocated (eventually), via Marshal::FreeHGlobal(), in order to avoid memory leak! That's why the MyFreeString helper function was added.
The application that I use to access dll's requires this calling convention:
DLL functions must be exported using the ìstandard Cî calling convention in order for TradeStation to locate them. Additionally, exported functions should be listed in the EXPORTS section of the DLL projectís module-definition (.DEF) file. The C++ code example below illustrates the use of __stdcall notation in a function
prototype. This is the function prototype for a DLL function called XAMPLEONCREATE, a function which receives a pointer to an IEasyLanguageObject as its sole argument, and returns an integer:
int __stdcall EXAMPLEONCREATE( IEasyLanguageObject * pELObj )
DLL functions must be exported using the ìstandard Cî calling convention in order for TradeStation to locate them.
This is the function prototype for a DLL function called XAMPLEONCREATE, a function which receives a pointer to an IEasyLanguageObject as its sole argument, and returns an integer: int __stdcall EXAMPLEONCREATE(IEasyLanguageObject * pELObj)
Note: We define the macro WARPPERLIBRARY_API as __declspec(dllexport) when building the DLL, and we define it as __declspec(dllimport) when using the DLL. This way, we can use the same header file (.h) for both cases!