Pinvoke issue in visual C# with C++ code - c#

I'm trying to code the "One-minute" example of reconstructMe SDK, however their SDK is in c++ I think, I succesfully created a console application as directed on their page (here), but I want to create a simple UI, however I'm not very familiar with Visual c++ (I do know something about c++), so I tried their example for C# (I'm pretty much familiar with their UI design) but I get this error when using the C# code provided (here):
A call to PInvoke function 'Lala!Lala.Reme::reme_context_compile' has
unbalanced the stack. This is likely because the managed PInvoke
signature does not match the unmanaged target signature. Check that
the calling convention and parameters of the PInvoke signature match
the target unmanaged signature.
I think is an issue of configuring the project or something like that.

The reconstructMe DLL is using the C calling convention (Cdecl) and not the Windows calling convention (StdCall). They differ in how the stack is handled, which is why having an incorrect calling convention results in a stack imbalance.
The default for p/Invoke is StdCall, you need to manually set the CallingConvension parameter to Cdecl on the DllImport attribute:
[DllImport("example.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int function(int param);

Related

Using a C++ library in C# winforms

I'm trying to use the SPARK particle system in OpenTK.
my project contains the header files in folders, with just two header files which only includes the others, and the folders contain the source files too.
I have tried several approaches so far, but nothing has worked for me yet, those are what I've tried:
1. P/Invoke
This is writing some code in your C++ project which built the dll and then using the DllImport attribute in C# (which obviously needs using System.Runtime.InteropServices;). I discovered the hard way that this doesn't work with classes, it only works for methods outside classes, so this approach was ineffective.
2. Wrapper classes
This is writing a class that contains a pointer to the original class. I discovered that the difficulty actually arises from calling unmanaged code(no automatic memory management) from managed code, that's why wrapper classes are needed, and that's why you have to redefine methods' signatures and let them call the original methods.
Of course this has advantages, like naming the classes and methods in a better way, but the library is so big so you can see the effort of this.
3. Use of an automatic wrapper:
This is a good approach, especially with xInterop++. I was really optimistic about this and thought it would work, it says "give me the .h files and the dll and I'll build the .NET dll for you". Good but doing so gives an error; in brief:
You must make sure .h files and the dll are consistent and that the
library works in a C++ project.
I have tried several things to deal with this error:
Knowing what the dll contains: it is difficult as I learned from Googling and from this site, so my try failed.
Putting header files in a new project and building it: received errors, fixed them, and then built the project and it worked well. I uploaded the dll file with the header files to xInterop. It then told the classes that were found but would then state that nothing was found! I searched and learned that the compiler must be told which classes are needed to be exposed by the dll by marking every class that is needed using the following statement:_declspec(dllexport).
I used Find & Replace to fix this thing and tried again and classes were shown, so I launched xInterop and received the same error.
It asked to ensure that the dll works. After verifying that the file worked I launched the program and linker errors were produced.
Here is where I'm stuck, these are the linker errors I get:
main.obj : error LNK2019: unresolved external symbol "void __cdecl
SPK::swapParticles(class SPK::Particle &,class SPK::Particle &)"
(?swapParticles#SPK##YAXAAVParticle#1#0#Z) referenced in function
"private: void __thiscall SPK::Pool::swapElements(class SPK::Particle &,class SPK::Particle
&)" (?swapElements#?$Pool#VParticle#SPK###SPK##AAEXAAVParticle#2#0#Z)
main.obj : error LNK2001: unresolved external symbol "unsigned int
SPK::randomSeed" (?randomSeed#SPK##3IA) main.obj : error LNK2001:
unresolved external symbol "unsigned long const SPK::NO_ID"
(?NO_ID#SPK##3KB) main.obj : error LNK2001: unresolved external symbol
"public: static float const * const SPK::Transformable::IDENTITY"
(?IDENTITY#Transformable#SPK##2QBMB)
This is the code that produced those errors:
#include "Extensions/Emitters/SPK_RandomEmitter.h"
using namespace SPK;
int main()
{
RandomEmitter e;
e.changeFlow(6);
e.getFlow();
return 0;
}
So that's my problem, I'm sorry for explaining too much but I've done a three days search without finding any solution.
PS:
the library is very big, so an automatic solution is a must.
This is a very, very unfriendly C++ library to have to interop with. Scratch the idea that pinvoke can work, C++ classes require C++/CLI wrappers. There are a great many classes with many small methods. The library depends on composition to generate effects so any approach that tries to do the interop with a few God classes is a dead avenue.
The most significant hazard is that it heavily relies on multiple inheritance. Not supported in .NET, this will defeat any tool that auto-generate wrappers. Also note that it only supports OpenGL rendering, not a terribly popular graphics api on Windows.
The library is attractive, and has been around for quite a while, but nobody has successfully ported it to .NET yet. This is unsurprising. In my opinion, you don't stand a chance. Only a rewrite could work.
PInvoke is the way to do what you are looking for. Doesn't matter if you have or do't have the code for that DLL so long you know the function signature.
Have a look at these articles from MSDN and code project that cover basics of PInvoke:
Platform Invoke Tutorial
P/Invoke Tutorial: Basics (Part 1)
Edit:
There are tools that can possibly generate DllImport signature for you. I have NOT tried any of these myself. Have a look:
P/Invoke Signature Generator
Easiest way to generate P/Invoke code?
This one
http://www.swig.org/
Hope that helps.
If your native dll exports some classes, then I would strongly suggest creating another native DLL wrapper for the original one. It should export a few functions and no classes at all.
Exported functioned could be something like:
my_lib_create_context( void ** const ppContext );
my_lib_delete_context( void * const pContext );
my_lib_do_something( void * const pContext, T param1, T param2 );
Inside my_lib_create_context() create an instance of your class and pass the pointer back through the ppContext parameter.
Inside my_lib_do_something() cast the pContext to a pointer of your class type and use it.
Also, when writing your wrapper, pay attention to calling convention, because you will need to pass that information to the .NET world (I think stdcall is default if not explicitly defined).
EDIT:
Regarding that part on how to do it:
Create a new C++ solution/project, select DLL type. Then add .def file to that project. Add to that file this:
EXPORTS
my_lib_create_context #1
my_lib_delete_context #2
my_lib_do_something #3
Then add some header file where you will put function signatures like this:
typedef void * SomeContext;
extern "C"
{
int __stdcall my_lib_create_context( /* [ out ] */ SomeContext * ppContext );
int __stdcall my_lib_delete_context( /* [ in ] */ SomeContext pContext );
// TO DO: ... you get it by now...
}
Implement these functions in .cpp file. Once you are done, create a wrapper in C# for this DLL and use it.
Hmm P/Invoke call GetProcessAdress .. so importing ABI problem is so so..
http://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class
here are your answer give credit to those guy

Passing Object as parameter in c /CLI Wrapper Function to be exported to native Win32 dll

I've been working recently in COM interop thing.Read some Good books about it C++/CLI in Action By Nishant Shivakumar. I also went through this link by Srinivas wherein he has explained beautifully how to Consume C# libraryin native C++ using C++/CLI.I downloaded the code present at the bottom of the page..Read it..And loved it.My application is loosely based on it. I have a question though in that example(which you can download it there).
In C# Library "Worker.cs",If I have a method in the Worker class with a signature like this::
public void GetStudent(ManagedStudent student,int ){....}
FYI:: I need the object parameter because I would be accessing a method from that class in the Worker Class.
In C++/CLI wrapper project, NativeInterface.h, I wanted to export a method which gets this managed object as a parameter unlike the example.
__declspec dllexport void GetStudent(ManagedStudent^ obj)
What is the equivalent of an object in C++/CLI?
And later I want to access this method by importing this method by passing an object in my native Win32 Application/DLL.
I am including the "NativeInterface.h" file in my native dll/App . But an error comes while building the dll/App..managed targeted code requires \clr option.
FYI::
1. My WIN32 dll/app is being compiled with no \clr support and my wrapper with \clr support
2. I believe the error comes because of the handle used as a parameter? I want to access UnmanagedStudent(Object obj) in native app/dll;
Is that possible
It's possible, but you can't pass a .NET object to a native DLL, which is a native C++ code...
The equivalent of an .NET object in native C++ is C++ object... but this is like asking a C# to understand Native or PHP, or....
So, there are several approaches.
Don't use C++ managed wrapper. Instead using Marsahling and C# interoperability directly call into native C++, in 1 of 2 ways:
Pass the object fields as a long list of parameters to the C++ and re-construct the object inside native C++. A bit "not nice" approach but very efficient and easy to debug.
You can also pass the object as a class pointer to the C++ native directly, you need first to create the right marshaling in C#. See here:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal(v=vs.110).aspx
Use C++ Interop (which you are doing...). You need to compile with Mixed mode! See this nice example:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/f2de75c5-50a6-41ac-9ddf-694a8c0ce75b/
BUT... you need to understand the basics and know how to compile it:
http://msdn.microsoft.com/en-us/library/x0w2664k.aspx
Interoperability is a complex issue... and I try to write a short answer, please revert to me for further clarifications....

System.ExecutionEngineException only when debugging

I am a C++ developer so I do not have much experience with C#, however, I have to fix this problem anyway.
There is a C# GUI which is using some C++ DLLs. When calling one of the methods from one of the DLLs a System.ExecutionEngineException occurs. Obviously I cant step into the C++ code to see if there is a problem with this code. So I build a small C++ testing application and this one worked fine. The parameters the method is called with in the C# code also look fine to me (used the same values in my C++ testing app). Although there is a problem somewhere in the GUI which may or may not be related to this issue, the same executable started without Visual Studio works just fine.
I have currently no idea on how to find out what causes the problem. Any hints will be highly appreciated.
Call to method in C# code where caseID is of type int, paramID is of type System.Int32 and paramData is a custom struct.
getParameter(caseID, dataID, paramID, ref paramData)
The signature of the method in the C# code looks like this:
[ DllImport ("helper.dll", CallingConvention=CallingConvention.Cdecl/*, CharSet = CharSet.Auto*/ )]
public static extern ERROR getParameter(System.Int32 caseID, System.Int32 dataID, System.Int32 paramID, ref PARAMETER_DATA data);
The signature of the corresponding method in the C++ DLL looks like this:
ERROR _stdcall getParameter(const long caseID, const long dataID, long number, PARAMETER_DATA *data);
What does look odd to me is that the C++ code explicitly states that the method should be called with calling convention "stdcall" whereas the C# code want to use Cdecl. However, this code seems to have worked for quite a while now. I also tried to change both calling conventions to stdcall but that did not work either.
The problem was that a struct member which is a char[] in C++ changed its size. In the C# code there was this attribute
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst=11)]
So I had to change the value of the SizeConst property. Don't know why I didn' see this when I first checked the structs for differences...
I also fixed the calling convention issue and now everything seems to work fine.

Writing C++ intended to be called from C#?

So I am doing this as a learning moment and I'm not afraid to say I have no idea what I'm doing here. It might also be worth mentioning that I don't know much about C++ in this scenario.
In C#, I've used DllImport plenty of times to bring in stuff from user32.dll or other DLLs that I haven't written, but I'm looking to better understand how the other half (the C++ half) is implemented to make this happen.
The C++ code I have is simple and just to verify that the call went through successfully:
#include <iostream>
using namespace std;
__declspec(dllexport) void HelloWorld() {
cout << "Hello, World" << endl;
}
I don't know what the importance of __declspec(dllexport) is, but I've seen it on a couple websites that didn't touch much on its importance.
My C# isn't very different than previous DllImports I've done before:
[DllImport("TestDLL.dll")]
static extern void HelloWorld();
static void Main(string[] args) {
HelloWorld();
}
I'm compiled the C++ DLL and put it in the C# project and it's copied to the bin folder. When I run the C# project I get an EntryPointNotFoundException at the call to HelloWorld() inside the main function.
My guess is that I need to either change the C++ code or the compilation flags of the C++ project. Currently "Use of MFC" is set to "Use Standard Windows Libraries" and there's no use of ATL or CLR. Any help would be greatly appreciated.
C++ is a language that supports overloading. In other words, you can have more than one version of HelloWorld(). You could also export HelloWorld(int), a distinct version. It is also a language that requires a linker. In order to not confuzzle the linker about the same name for different functions, the compiler decorates the name of the function. Aka "name mangling".
The tool you want to use to troubleshoot problems like this is Dumpbin.exe. Run it from the Visual Studio Command Prompt on your DLL with the /exports option. You'll see this:
ordinal hint RVA name
1 0 000110EB ?HelloWorld##YAXXZ = #ILT+230(?HelloWorld##YAXXZ)
Bunch of gobbledegook, the exported name is shown in parentheses. Note the ? in the front and ##YAXXZ after the name, that's why the CLR cannot find the exported function. A function that takes an int argument will be exported as ?HelloWorld##YAXH#Z (try it).
The [DllImport] directive supports this, you can use EntryPoint property to give the exported name. Or you can tell the C++ compiler that it should generate code that a C compiler can use. Put extern "C" in front of the declaration and the C++ compiler will suppress the name decoration. And won't support function overloads anymore of course. Dumpbin.exe now shows this:
ordinal hint RVA name
1 0 00011005 HelloWorld = #ILT+0(_HelloWorld)
Note that the name is still not plain "HelloWorld", there's an underscore in front of the name. That's a decoration that helps catch mistakes with the calling convention. In 32-bit code there are 5 distinct ways to call a function. Three of which are common with DLLs, __cdecl, __stdcall and __thiscall. The C++ compiler defaults to __cdecl for regular free functions.
This is also a property of the [DllImport] attribute, the CallingConvention property. The default that's used if it isn't specified is CallingConvention.StdCall. Which matches the calling convention for many DLLs, particularly the Windows ones, but doesn't match the C++ compiler's default so you still have a problem. Simply use the property or declare your C++ function like this:
extern "C" __declspec(dllexport)
void __stdcall HelloWorld() {
// etc..
}
And the Dumpbin.exe output now looks like:
ordinal hint RVA name
1 0 000110B9 _HelloWorld#0 = #ILT+180(_HelloWorld#0)
Note the added #0, it describes the size of the stack activation frame. In other words, how many bytes worth of arguments are passed. This helps catch a declaration mistake at link time, such mistakes are extremely difficult to diagnose at runtime.
You can now use the [DllImport] attribute as you originally had it, the pinvoke marshaller is smart enough to sort out the decoration of the actual function. You can help it with the ExactSpelling and EntryPoint properties, it will be slightly quicker but nothing you'd ever notice.
First question last: __declspec(dllexport) is just a hint to the compiler that you intend to export the function from a DLL. It will generate a wee bit of extra code that can help making the exported function call faster (nothing the CLR uses). And passes an instruction to the linker that the function needs to be exported. Exporting functions can also be done with a .def file but that's doing it the hard way.
This is probably the best way to do it: How to import and use a unmanaged C++ class from C#?
I would recommend that you create a C++/CLI project which statically links with your pure C++. The C++/CLI project will generate the DLL and you will use it just like any other DLL in C#. Again, see the link above.
There ae basically two things that are going to influence name mangling which is why you are having trouble importing the function which are if extern "C" is around your function definition and the calling convention of your function.
extern "C" with a cdecl calling convention will give you a clean name that is easy to import, but you will need to add the calling convention to the DllImportAttribute.

Calling a native callback from managed .NET code (when loading the managed code using COM)

I am really confused by the multitude of misinformation about native / managed interop.
I have a regular C++ exe which is NOT built using CLR stuff (it is neither Managed C++ nor C++/CLI and never will be). This C++ exe is "in charge", there is no managed wrapper for it.
I would like to access some code I have in a C# assembly from my C++ exe. I can access the C# assembly from my C++ code using COM. However, when my C# code detects an event I would like it to call back into my C++ code. The C++ function pointer to call back into will be provided at runtime. Note that the C++ function pointer is to a function found in the exe's execution environment. It may use static members from there. I don't want the managed code to try and load up some DLL to call a function (there is no DLL).
How do I pass this C++ function pointer to my C# code through COM/.NET and have my C# code successfully call it?
Thanks!
You'll probably want to use Marshal.GetDelegateForFunctionPointer:
Create a delegate type that matches the signature of the native function, keeping in mind the right way to marshal types and using MarshalAs as needed
Communicate the native function pointer from your native code to your C# code however you can (in your case, it looks like you can use your COM -> C# connection)
Use Marshal.GetDelegateForFunctionPointer to turn the pointer into a C#-callable delegate
Invoke the delegate with your parameters
Junfeng Zhang has an example of doing this here.
Note the restrictions mentioned on MSDN:
The GetDelegateForFunctionPointer
method has the following restrictions:
Generics are not supported in interop
scenarios.
You cannot pass an invalid function
pointer to this method.
You can use this method only for pure
unmanaged function pointers.
You cannot use this method with
function pointers obtained through C++
or from the GetFunctionPointer method.
You cannot use this method to create a
delegate from a function pointer to
another managed delegate.
The part about C++ is likely referring to function pointers for class methods. This should still work for global functions.
The standard COM approach is to subscribe to an event that's raised by the COM server. Use can use the event keyword in C#, CLR interop automatically implements the COM glue that's needed. Use the IConnectionPoint interface in your C++ code. Backgrounder is here.

Categories