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.
Related
I am working on a rather large codebase in which C++ functionality is P/Invoked from C#.
There are many calls in our codebase such as...
C++:
extern "C" int __stdcall InvokedFunction(int);
With a corresponding C#:
[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
private static extern int InvokedFunction(IntPtr intArg);
I have scoured the net (insofar as I am capable) for the reasoning as to why this apparent mismatch exists. For example, why is there a Cdecl within the C#, and __stdcall within the C++? Apparently, this results in the stack being cleared twice, but, in both cases, variables are pushed onto the stack in the same reverse order, such that I do not see any errors, albeit the possibility that return information is cleared in the event of attempting a trace during debugging?
From MSDN: http://msdn.microsoft.com/en-us/library/2x8kf7zx%28v=vs.100%29.aspx
// explicit DLLImport needed here to use P/Invoke marshalling
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl, CharSet = CharSet::Ansi)]
// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
Once again, there is both extern "C" in the C++ code, and CallingConvention.Cdecl in the C#. Why is it not CallingConvention.Stdcall? Or, moreover, why is there __stdcall in the C++?
Thanks in advance!
This comes up repeatedly in SO questions, I'll try to turn this into a (long) reference answer. 32-bit code is saddled with a long history of incompatible calling conventions. Choices on how to make a function call that made sense a long time ago but are mostly a giant pain in the rear end today. 64-bit code has only one calling convention, whomever is going to add another one is going to get sent to small island in the South Atlantic.
I'll try to annotate that history and relevance of them beyond what's in the Wikipedia article. Starting point is that the choices to be made in how to make a function call are the order in which to pass the arguments, where to store the arguments and how to cleanup after the call.
__stdcall found its way into Windows programming through the olden 16-bit pascal calling convention, used in 16-bit Windows and OS/2. It is the convention used by all Windows api functions as well as COM. Since most pinvoke was intended to make OS calls, Stdcall is the default if you don't specify it explicitly in the [DllImport] attribute. Its one and only reason for existence is that it specifies that the callee cleans up. Which produces more compact code, very important back in the days when they had to squeeze a GUI operating system in 640 kilobytes of RAM. Its biggest disadvantage is that it is dangerous. A mismatch between what the caller assumes are the arguments for a function and what the callee implemented causes the stack to get imbalanced. Which in turn can cause extremely hard to diagnose crashes.
__cdecl is the standard calling convention for code written in the C language. Its prime reason for existence is that it supports making function calls with a variable number of arguments. Common in C code with functions like printf() and scanf(). With the side effect that since it is the caller that knows how many arguments were actually passed, it is the caller that cleans up. Forgetting CallingConvention = CallingConvention.Cdecl in the [DllImport] declaration is a very common bug.
__fastcall is a fairly poorly defined calling convention with mutually incompatible choices. It was common in Borland compilers, a company once very influential in compiler technology until they disintegrated. Also the former employer of many Microsoft employees, including Anders Hejlsberg of C# fame. It was invented to make argument passing cheaper by passing some of them through CPU registers instead of the stack. It is not supported in managed code due to the poor standardization.
__thiscall is a calling convention invented for C++ code. Very similar to __cdecl but it also specifies how the hidden this pointer for a class object is passed to instance methods of a class. An extra detail in C++ beyond C. While it looks simple to implement, the .NET pinvoke marshaller does not support it. A major reason that you cannot pinvoke C++ code. The complication is not the calling convention, it is the proper value of the this pointer. Which can get very convoluted due to C++'s support for multiple inheritance. Only a C++ compiler can ever figure out what exactly needs to be passed. And only the exact same C++ compiler that generated the code for the C++ class, different compilers have made different choices on how to implement MI and how to optimize it.
__clrcall is the calling convention for managed code. It is a blend of the other ones, this pointer passing like __thiscall, optimized argument passing like __fastcall, argument order like __cdecl and caller cleanup like __stdcall. The great advantage of managed code is the verifier built into the jitter. Which makes sure that there can never be an incompatibility between caller and callee. Thus allowing the designers to take the advantages of all of these conventions but without the baggage of trouble. An example of how managed code could stay competitive with native code in spite of the overhead of making code safe.
You mention extern "C", understanding the significance of that is important as well to survive interop. Language compilers often decorate the names of exported function with extra characters. Also called "name mangling". It is a pretty crappy trick that never stops causing trouble. And you need to understand it to determine the proper values of the CharSet, EntryPoint and ExactSpelling properties of a [DllImport] attribute. There are many conventions:
Windows api decoration. Windows was originally a non-Unicode operating system, using 8-bit encoding for strings. Windows NT was the first one that became Unicode at its core. That caused a rather major compatibility problem, old code would not have been able to run on new operating systems since it would pass 8-bit encoded strings to winapi functions that expect a utf-16 encoded Unicode string. They solved this by writing two versions of every winapi function. One that takes 8-bit strings, another that takes Unicode strings. And distinguished between the two by gluing the letter A at the end of the name of the legacy version (A = Ansi) and a W at the end of the new version (W = wide). Nothing is added if the function doesn't take a string. The pinvoke marshaller handles this automatically without your help, it will simply try to find all 3 possible versions. You should however always specify CharSet.Auto (or Unicode), the overhead of the legacy function translating the string from Ansi to Unicode is unnecessary and lossy.
The standard decoration for __stdcall functions is _foo#4. Leading underscore and a #n postfix that indicates the combined size of the arguments. This postfix was designed to help solve the nasty stack imbalance problem if the caller and callee don't agree about the number of arguments. Works well, although the error message isn't great, the pinvoke marshaller will tell you that it cannot find the entrypoint. Notable is that Windows, while using __stdcall, does not use this decoration. That was intentional, giving programmers a shot at getting the GetProcAddress() argument right. The pinvoke marshaller also takes care of this automatically, first trying to find the entrypoint with the #n postfix, next trying the one without.
The standard decoration for __cdecl function is _foo. A single leading underscore. The pinvoke marshaller sorts this out automatically. Sadly, the optional #n postfix for __stdcall does not allow it to tell you that your CallingConvention property is wrong, great loss.
C++ compilers use name mangling, producing truly bizarre looking names like "??2#YAPAXI#Z", the exported name for "operator new". This was a necessary evil due to its support for function overloading. And it originally having been designed as a preprocessor that used legacy C language tooling to get the program built. Which made it necessary to distinguish between, say, a void foo(char) and a void foo(int) overload by giving them different names. This is where the extern "C" syntax comes into play, it tells the C++ compiler to not apply the name mangling to the function name. Most programmer that write interop code intentionally use it to make the declaration in the other language easier to write. Which is actually a mistake, the decoration is very useful to catch mismatches. You'd use the linker's .map file or the Dumpbin.exe /exports utility to see the decorated names. The undname.exe SDK utility is very handy to convert a mangled name back to its original C++ declaration.
So this should clear up the properties. You use EntryPoint to give the exact name of the exported function, one that might not be a good match for what you want to call it in your own code, especially for C++ mangled names. And you use ExactSpelling to tell the pinvoke marshaller to not try to find the alternative names because you already gave the correct name.
I'll nurse my writing cramp for a while now. The answer to your question title should be clear, Stdcall is the default but is a mismatch for code written in C or C++. And your [DllImport] declaration is not compatible. This should produce a warning in the debugger from the PInvokeStackImbalance Managed Debugger Assistant, a debugger extension that was designed to detect bad declarations. And can rather randomly crash your code, particularly in the Release build. Make sure you didn't turn the MDA off.
cdecl and stdcall are both valid and usable between C++ and .NET, but they should consistent between the two unmanaged and managed worlds. So your C# declaration for InvokedFunction is invalid. Should be stdcall. The MSDN sample just gives two different examples, one with stdcall (MessageBeep), and one with cdecl (printf). They are unrelated.
I am working on a rather large codebase in which C++ functionality is P/Invoked from C#.
There are many calls in our codebase such as...
C++:
extern "C" int __stdcall InvokedFunction(int);
With a corresponding C#:
[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
private static extern int InvokedFunction(IntPtr intArg);
I have scoured the net (insofar as I am capable) for the reasoning as to why this apparent mismatch exists. For example, why is there a Cdecl within the C#, and __stdcall within the C++? Apparently, this results in the stack being cleared twice, but, in both cases, variables are pushed onto the stack in the same reverse order, such that I do not see any errors, albeit the possibility that return information is cleared in the event of attempting a trace during debugging?
From MSDN: http://msdn.microsoft.com/en-us/library/2x8kf7zx%28v=vs.100%29.aspx
// explicit DLLImport needed here to use P/Invoke marshalling
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl, CharSet = CharSet::Ansi)]
// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
Once again, there is both extern "C" in the C++ code, and CallingConvention.Cdecl in the C#. Why is it not CallingConvention.Stdcall? Or, moreover, why is there __stdcall in the C++?
Thanks in advance!
This comes up repeatedly in SO questions, I'll try to turn this into a (long) reference answer. 32-bit code is saddled with a long history of incompatible calling conventions. Choices on how to make a function call that made sense a long time ago but are mostly a giant pain in the rear end today. 64-bit code has only one calling convention, whomever is going to add another one is going to get sent to small island in the South Atlantic.
I'll try to annotate that history and relevance of them beyond what's in the Wikipedia article. Starting point is that the choices to be made in how to make a function call are the order in which to pass the arguments, where to store the arguments and how to cleanup after the call.
__stdcall found its way into Windows programming through the olden 16-bit pascal calling convention, used in 16-bit Windows and OS/2. It is the convention used by all Windows api functions as well as COM. Since most pinvoke was intended to make OS calls, Stdcall is the default if you don't specify it explicitly in the [DllImport] attribute. Its one and only reason for existence is that it specifies that the callee cleans up. Which produces more compact code, very important back in the days when they had to squeeze a GUI operating system in 640 kilobytes of RAM. Its biggest disadvantage is that it is dangerous. A mismatch between what the caller assumes are the arguments for a function and what the callee implemented causes the stack to get imbalanced. Which in turn can cause extremely hard to diagnose crashes.
__cdecl is the standard calling convention for code written in the C language. Its prime reason for existence is that it supports making function calls with a variable number of arguments. Common in C code with functions like printf() and scanf(). With the side effect that since it is the caller that knows how many arguments were actually passed, it is the caller that cleans up. Forgetting CallingConvention = CallingConvention.Cdecl in the [DllImport] declaration is a very common bug.
__fastcall is a fairly poorly defined calling convention with mutually incompatible choices. It was common in Borland compilers, a company once very influential in compiler technology until they disintegrated. Also the former employer of many Microsoft employees, including Anders Hejlsberg of C# fame. It was invented to make argument passing cheaper by passing some of them through CPU registers instead of the stack. It is not supported in managed code due to the poor standardization.
__thiscall is a calling convention invented for C++ code. Very similar to __cdecl but it also specifies how the hidden this pointer for a class object is passed to instance methods of a class. An extra detail in C++ beyond C. While it looks simple to implement, the .NET pinvoke marshaller does not support it. A major reason that you cannot pinvoke C++ code. The complication is not the calling convention, it is the proper value of the this pointer. Which can get very convoluted due to C++'s support for multiple inheritance. Only a C++ compiler can ever figure out what exactly needs to be passed. And only the exact same C++ compiler that generated the code for the C++ class, different compilers have made different choices on how to implement MI and how to optimize it.
__clrcall is the calling convention for managed code. It is a blend of the other ones, this pointer passing like __thiscall, optimized argument passing like __fastcall, argument order like __cdecl and caller cleanup like __stdcall. The great advantage of managed code is the verifier built into the jitter. Which makes sure that there can never be an incompatibility between caller and callee. Thus allowing the designers to take the advantages of all of these conventions but without the baggage of trouble. An example of how managed code could stay competitive with native code in spite of the overhead of making code safe.
You mention extern "C", understanding the significance of that is important as well to survive interop. Language compilers often decorate the names of exported function with extra characters. Also called "name mangling". It is a pretty crappy trick that never stops causing trouble. And you need to understand it to determine the proper values of the CharSet, EntryPoint and ExactSpelling properties of a [DllImport] attribute. There are many conventions:
Windows api decoration. Windows was originally a non-Unicode operating system, using 8-bit encoding for strings. Windows NT was the first one that became Unicode at its core. That caused a rather major compatibility problem, old code would not have been able to run on new operating systems since it would pass 8-bit encoded strings to winapi functions that expect a utf-16 encoded Unicode string. They solved this by writing two versions of every winapi function. One that takes 8-bit strings, another that takes Unicode strings. And distinguished between the two by gluing the letter A at the end of the name of the legacy version (A = Ansi) and a W at the end of the new version (W = wide). Nothing is added if the function doesn't take a string. The pinvoke marshaller handles this automatically without your help, it will simply try to find all 3 possible versions. You should however always specify CharSet.Auto (or Unicode), the overhead of the legacy function translating the string from Ansi to Unicode is unnecessary and lossy.
The standard decoration for __stdcall functions is _foo#4. Leading underscore and a #n postfix that indicates the combined size of the arguments. This postfix was designed to help solve the nasty stack imbalance problem if the caller and callee don't agree about the number of arguments. Works well, although the error message isn't great, the pinvoke marshaller will tell you that it cannot find the entrypoint. Notable is that Windows, while using __stdcall, does not use this decoration. That was intentional, giving programmers a shot at getting the GetProcAddress() argument right. The pinvoke marshaller also takes care of this automatically, first trying to find the entrypoint with the #n postfix, next trying the one without.
The standard decoration for __cdecl function is _foo. A single leading underscore. The pinvoke marshaller sorts this out automatically. Sadly, the optional #n postfix for __stdcall does not allow it to tell you that your CallingConvention property is wrong, great loss.
C++ compilers use name mangling, producing truly bizarre looking names like "??2#YAPAXI#Z", the exported name for "operator new". This was a necessary evil due to its support for function overloading. And it originally having been designed as a preprocessor that used legacy C language tooling to get the program built. Which made it necessary to distinguish between, say, a void foo(char) and a void foo(int) overload by giving them different names. This is where the extern "C" syntax comes into play, it tells the C++ compiler to not apply the name mangling to the function name. Most programmer that write interop code intentionally use it to make the declaration in the other language easier to write. Which is actually a mistake, the decoration is very useful to catch mismatches. You'd use the linker's .map file or the Dumpbin.exe /exports utility to see the decorated names. The undname.exe SDK utility is very handy to convert a mangled name back to its original C++ declaration.
So this should clear up the properties. You use EntryPoint to give the exact name of the exported function, one that might not be a good match for what you want to call it in your own code, especially for C++ mangled names. And you use ExactSpelling to tell the pinvoke marshaller to not try to find the alternative names because you already gave the correct name.
I'll nurse my writing cramp for a while now. The answer to your question title should be clear, Stdcall is the default but is a mismatch for code written in C or C++. And your [DllImport] declaration is not compatible. This should produce a warning in the debugger from the PInvokeStackImbalance Managed Debugger Assistant, a debugger extension that was designed to detect bad declarations. And can rather randomly crash your code, particularly in the Release build. Make sure you didn't turn the MDA off.
cdecl and stdcall are both valid and usable between C++ and .NET, but they should consistent between the two unmanaged and managed worlds. So your C# declaration for InvokedFunction is invalid. Should be stdcall. The MSDN sample just gives two different examples, one with stdcall (MessageBeep), and one with cdecl (printf). They are unrelated.
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
I got a friend who made some cool functions dealing with encryption and security that he made me in C++. He then used themidia to make it more secure and such.
He gave me the DLL and I used a function finder to find all the functions. But here is the problem.
All functions have an # symbol in them, and when in C# I use a DLL important it says can't compile code for it is a syntax error on the #. For example a function name might be "CheckPassword_#12" which is weird, but C# wont allow me to have that.
Is there something I am missing, he wont give me a unsecured DLL for he does not want people if they crack my application to be able to modify his DLL. I checked multiple applications and did stuff my self but all the functions names are coming up with a #.
Thanks!
[DllImport("security.dll", CallingConvention=CallingConvention.StdCall, ExactSpelling=true)]
private static extern IntPtr _passwordValid#8(string string_0, string string_1);
That makes more sense than your question. The StdCall calling convention puts an underscore before the identifier, a #n after the identifier. This name decoration helps to catch declaration errors in a C program. You simply omit them, the pinvoke marshaller can reverse-engineer the property export name. StdCall is the default so this is good enough:
[DllImport("security.dll")]
private static extern IntPtr passwordValid(string string_0, string string_1);
Btw, I meant to say EntryPoint instead of ExactSpelling in my comment.
One more detail, you may need to use the CharSet property in the declaration. Whether you need it depends on the string type that the DLL author used. A DLL writer normally also supplies a .h file with the function declarations. Such an .h file would also say passwordValid and not _passwordValid#8. Do make sure you have the legal right to use this DLL, not having such a header file is very unusual.
I wrote my program in C++ and exported it as a DLL. I have a C# WPF GUI and I want to import the DLL to do the processing.
I am very new to C#. How can I use the C++ class in C#? I know I can't just use the .h file.
Because I used pointers in C++, in C# I couldn't use pointers. That's why I got confused. Like in C++ i used char* instead of string, and I need to return double* for a big collection of double data, and things like that.
There are a number of ways:
Export the DLL functions and use DllImportAttribute to P/Invoke into the DLL.
If it is a COM DLL, then you can generate a Runtime Callable Wrapper via TLBIMP.exe
You can use C++/CLI to build create a .Net assembly which loads and calls methods on the DLL natively.
To address your additional concerns, yes, you can use pointers in C#. If you have a function which has a double* parameter, you can declare that in C# like this:
[DllImport("Your.DLL")]
private static extern unsafe void DoProcessing(double* data, int dataSize);
You need to make sure you check the "Allow Unsafe Code" checkbox on the build tab of the C# project, and after that, you can use pointers to your heart's content.
However, note that while I'm providing the pointer signature here, since you are obviously comfortable with pointers, there are other signatures which could be more safe for you to use, and would not require you to compile C# with unsafe code. The standard marshaller in the CLR will take care of the conversion from a pointer to a C# array, provided you give it a bit of a hint if the length is required:
[DllImport("Your.DLL")]
private static extern void DoProcessing(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] double[] data,
int dataSize);
This instructs the marshaller to use the parameter at index 1 (the 2nd parameter) as the size of the array of doubles pointed at by the 1st parameter. This allows you to avoid pointers in C#, and use safe CLI types. However, if you like pointers, my advice is to just use them - the C# will be easier for you than having to figure out how to write the method signature without them.
For more details on P/Invoke, refer to this documentation: http://msdn.microsoft.com/en-us/library/aa288468(VS.71).aspx
A lot depends on the structure of your C++ dll. If you have just a handful of functions, and they are not member functions of a class, then you can make them "extern C" functions and use the P/Invoke capability in .NET (sometimes called DllImport because of the attribute you use) to access the functions from C#.