Using a C++ library in C# winforms - c#

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

Related

how to reference imagesearch.dll to c# winforms?

I can't reference ImageSearch.dll in my project. I've been trying for days and can't get any further. it seems to me that i'm the only one with this problem and i don't know what to do next. Is it possible to reference a .dll manually, for example via lines of code? It's nerve wracking and need this or a similar feature.
I keep getting the following error:
Could not add a reference to imagesearch.dll. Make sure the file is accessible and is a valid assembly or COM component.
enter image description here
Hope someone can help me...
That message is telling you that the dll you're trying to reference is something that .NET doesn't know how to work with automatically. This means it has no idea what functions are in the dll or how they work. So, if a dll isn't a .NET assembly or exposed via COM, then you can use PInvoke (Platform Invoke).
Don't add the dll as a reference to your project at all, instead add it as a content file that gets output with the rest of your compiled code. Getting PInvoke to work with an arbitrary DLL can be quite complicated, so be prepared for some headaches. There's an entire website with examples of how to pinvoke for all sorts of libraries at http://pinvoke.net/ that will give you lots of ideas.
Then you can call methods in the dll by doing something like:
// Import ImageSearch.dll (containing the function we need) and define
// the method corresponding to the native function.
[DllImport("ImageSearch.dll"]
private static extern int FindImage(string imagePath);
Obviously I have no idea what imagesearch.dll is or does, so I have no idea what the actual PInvoke function should look like, you'll have to figure that out from the dll's interface.
https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke

C++/CLI Including Native Functions with parameters defaulted to NULL

I hope this isn't a dupe; I fear I don't know right thing to search so I'll just explain my problem.
I'm wrapping a large 3rd Party C/C++ API with C++/CLI so I can then use those final assemblies in a .Net C# plugin framework for a larger application.
The API does come with some documentation, headers, dll, and lib files so the first setup was easy: in Visual Studio 2013 I started a CLR/Class Library project add the files to the folder, add include directories/dependencies/using directories to the configuration sheets.
However, trying to use the exported global functions of the API throw a list of errors because the parameters are defaulted to NULL
APPIMPEXP void GetPartner(TCHAR* pHst = NULL)
Fails because(C2065) 'NULL' : undeclared identifier
So prior to included I tried one ugly hack after another
#define NULL nullptr;
Same line now has the error(C2143) syntax error:missing ')' before ;
#define NULL 0
Same error.
extern "C"
{
#include "apidll.h"
}
Same error
I've done very little with CLI before this, but I'm surprised I'm stumped so early. Is my only option PInvoke? I had initially tried to avoid that way because the API is heavily dependent on callbacks and I had finally determined a way to marshal delegates to callbacks.
#define NULL nullptr;
This one strikes me as the most correct of the things you tried to do (although someone more versed in C++ may have a different opinion). However, there's an error there: Remove the semicolon. Remember that #defines are simple text substitution, so that method becomes GetPartner(TCHAR* pHst = nullptr;), which is not correct.

How to reference .inl and .h files in C#

Update 1:
I am wondering whether I can reference to a .lib file, but it seems that I cannot.
If this is true, and I have no source code of the C++ project, How can I use its methods?
Btw, I'm using FastCV library.
I come across a situation that I need to call C++ methods from C# code.
The C++ generated files structure:
lib
--libfastcv.lib
--vc120.pdb inc
--fastcv.h
--fastcv.inl
--stdint.h
I know how to call C++ methods from C# :
[DllImport("libfastcv.lib",CallingConvention=CallingConvention.Cdecl)]
public static extern <ReturnType> <MethodName>(<Parameters>);
But I think the .h and .inl files need to be included in my C# project as well.
So how to include them?
Thank you very much.
They don't. Instead, you need to build/use binary-compatible types in your own code, and use them. (And, you importing a method from dll, not from lib).
You dont have to do any includes. The DLLImport should be enough.
To see the Methods you can import you can use DependencyWalker or my favourite Tool CFF Explorer
I often used any WINAPI functions where i need some constants defined in headers. I always had to define them in my C# code too, theres no way to "import" them.

Import a C++ .lib and .h file into a C# project?

I have just started a C# project and want to import a C++ .lib and it's corresponding header (.h) file.
I've read various posts that all mention .dll, rather than .lib, which is confusing me.
The image below shows the .lib and .h file I'm referring to, all I've done is drag them into the project.
Can anyone point me to a clearer explanation of how to go about doing this? I'm sure it can't be as hard as it seems.
This is, unfortunately, a non-trivial problem.
The reason is primarily due to the fact that C++ is an unmanaged language. C# is a managed language. Managed and unmanaged refers to how a language manages memory.
C++ you must do your own memory management (allocating and freeing),
C# .NET Framework does memory management with a garbage collector.
In your library code
You must make sure all of the places you call new, must call delete, and the same goes for malloc and free if you are using the C conventions.
You will have to create a bunch of wrapper classes around your function calls, and make sure you aren't leaking any memory in your C++ code.
The problem
Your main problem (to my knowledge) is you won't be able to call those functions straight in C# because you can't statically link unmanaged code into managed code.
You will have to write a .dll to wrap all your library functions in C++. Once you do, you can use the C# interop functionality to call those functions from the dll.
[DllImport("your_functions.dll", CharSet = CharSet.Auto)]
public extern void your_function();
What you could do, is creating a C++/CLI wrapper and expose the functionality of the lib you want to use via your wrapper. The created wrapper dll you can easily reference in your C# project. This of course takes a little bit of work to create the managed/unmanaged wrapper, but will pay off in the long run.
To create a managed C++ project select under the C++ project templates CLR and Class Library. Here you can link to your lib, use the header file the way you are used to.
Next create a new class (ref class) and wrap your library in it. An example might look something like this:
LibHeader.h
int foo(...);
You write a wrapper class like this:
Header:
Wrapper.h
public ref class MyWrapper
{
public:
int fooWrapped();
};
Your Implementation:
Wrapper.cpp
#include Libheader.h
int MyWrapper::fooWrapped()
{
return foo();
}
Namespaces and all the good stuff omitted for simplicity.
Now you can use MyWrapper in your C# code just as easy as any other managed class. Of course when the interface of the lib gets more complicated you have to think about it a bit more, but it might help to separate the lib-code from your application. Hope to have shed some light on it.
It is 'as hard as it seems'. C++ and C# are ambivalent. The first has deterministic destruction, the second not. Now, you write C++/cli delaying the destruction to some finalizer called by the garbage collector working in it's own thread, introducing problems all over the place (thread safety, are C++ members (used in c++/cli) valid?, ...). Even worse the GC might suggest C++ objects being tiny (a pointer) and provoke a kind of memory leak (due to late deallocating tiny objects). Essentially you end up in writing a GC on top of the C++/cli GC to delete non C++/cli (!) objects in the main thread or another. All that is insane, ...

Translate C++/CLI to C#

I have a small to medium project that is in C++/CLI. I really hate the syntax extensions of C++/CLI and I would prefer to work in C#. Is there a tool that does a decent job of translating one to the other?
EDIT: When I said Managed c++ before I apparently meant c++/CLI
You can only translate Managed C++ code (and C++/CLI code) to C# if the C++ code is pure managed. If it is not -- i.e. if there is native code included in the sources -- tools like .NET Reflector won't be able to translate the code for you.
If you do have native C++ code mixed in, then I'd recommend trying to move the native code into a separate DLL, replace your calls to DLL functions by easily identifiable stub functions, compile your project as a pure .NET library, then use .NET reflector to de-compile into C# code. Then you can replace the calls to the stub functions by p-invoke calls to your native DLL.
Good luck! I feel for you!
.NET Managed C++ is like a train wreck. But have you looked into C++ CLI? I think Microsoft did a great job in this field to make C++ a first class .NET citizen.
http://msdn.microsoft.com/en-us/magazine/cc163852.aspx
I'm not sure if this will work, but try using .Net Reflector along with ReflectionEmitLanguage plug-in. The RelelectionEmitLanguage plug-in claims to convert your assembly to c# code.
It has to be done manually unfortunately, but if the code is mostly C++/CLI (not native C++) then it can actually be done pretty quickly. I managed to port around 250,000 lines of C++/CLI code into C# in less than a couple of months, and I don't even know C++ very well at all.
If preserving Git history is important, you might want to git mv your cpp file into a cs file, commit, then start porting. The reason for this is that Git will think your file is new if you modify it too much after renaming it.
This was my approach when porting large amounts of code (so that it wouldn't take forever):
Create another worktree / clone of the branch and keep it open at all times
This is extremely important as you will want to compare your C# to the old C++/CLI code
Rename cpp to cs, delete header file, commit
I chose to rename the cpp file since its git history is probably more important than the header file
Create namespace + class in cs file, add any base classes/interfaces (if abstract sealed, make static in C#)
Copy fields first, then constructors, then properties, and finally functions
Start replacing with Ctrl+H:
^ to empty
:: to .
-> to .
nullptr to null
for each to foreach
gcnew to new
L" to "
Turn on case sensitivity to avoid accidental renames (for example L"cool" should become "cool", not "coo"
Prefixes like ClassName:: to empty, so that MyClass::MyMethod becomes MyMethod
Go through the red code and port manually code that cannot be just replaced (e.g. some special C++ casts), unless you have some cool regex to do it fast
Once code compiles, go through it again, compare to C++/CLI line by line, check for errors, clean it up, move on.
If you encounter a dependency that needs to be ported, you could pause, port that, then come back. I did that, but it might not be so easy.
Properties were the most annoying to port, because I had to remove everything before and after the getters and setters. I could have maybe written a regex for it but didn't bother doing so.
Once the porting is done, it's very important that you go through the changes line by line, read the code, and compare with C++/CLI code and fix possible errors.
One problem with this approach is that you can introduce bugs in variable declarations, because in C++/CLI you can declare variables in 2 ways:
MyType^ variable; <- null
MyType variable; <- calls default constructor
In the latter case, you want to actually do MyType variable = new MyType(); but since you already removed all the ^ you have to just manually check and test which one is correct. You could of course just replace all ^'s manually, but for me it would have taken too long (plus laziness) so I just did it this way.
Other recommendations:
Have a dummy C++/CLI project and a tool like LinqPad or another C# project to test differences between C++/CLI and C# if you're unsure of a piece of ported code
Install Match Margin to help highlight similar code (helped me when porting WinForms code)
ReSharper! It helped with finding bugs and cleaning up the code a LOT. Truly worth the money.
Some gotchas that I encountered while porting:
Base classes can be called in C++/CLI like so: BaseClass->DoStuff, but in C# you would have to do base.DoStuff instead.
C++/CLI allows such statements: if (foo), but in C# this has to be explicit. In the case of integers, it would be if (foo != 0) or for objects if (foo != null).
Events in base classes can be invoked in C++/CLI, but in C# it's not possible. The solution is to create a method, like OnSomeEvent, in the base class, and inside that to invoke the event.
C++/CLI automatically generates null checks for event invocations, so in C# make sure to add an explicit null check: MyEvent?.Invoke(this, EventArgs.Empty);. Notice the question mark.
dynamic_cast is equivalent to as cast in C#, the rest can be direct casts ((int) something).
gcnew can be done without parentheses. In C# you must have them with new.
Pay attention to virtual override keywords in the header files, you can easily forget to mark the C# methods with override keyword.
Intefaces can have implementations! In this case, you might have to rethink the architecture a bit. One option is to pull the implementation into an abstract class and derive from it
Careful when replacing casts with Convert calls in C#
Convert.ToInt32 rounds to the narest int, but casting always rounds down, so in this case we should not use the converter.
Always try casting first, and if that doesn't work, use the Convert class.
Variables in C++/CLI can be re-declared in a local scope, but in C# you get naming conflicts. Code like this easily lead to hard to find bugs if not ported carefully.
Example: An event handler can take a parameter e, but also has a try-catch like catch (Exception e) which means there are 2 e variables.
Another example:
// number is 2
int number = 2;
for (int number = 0; number < 5; number++)
{
// number is now 0, and goes up to 4
}
// number is again 2!
The above code is illegal in C#, because there is a naming conflict. Find out exactly how the code works in C++ and port it with the exact same logic, and obviously use different variable names.
In C++/CLI, it's possible to just write throw; which would create a generic C++ exception SEHException. Just replace it with a proper exception.
Be careful when porting code that uses the reference % sign, that usually means that you will have to use ref or out keywords in C#.
Similarly, pay attention to pointers * and & references. You might have to write additional code to write changes back whereas in C++ you can just modify the data pointed to by the pointer.
It's possible to call methods on null object instances in C++/CLI. Yes seriously. So inside the function you could do If (this == null) { return; }.
Port this type of code carefully. You might have to create an extension method that wraps over this type of method in order to avoid breaking the code.
Check and make sure everything in the old project file vcxproj was ported correctly. Did you miss any embedded resources?
Careful when porting directives like #ifdef, the "if not" (#ifndef) looks awfully similar but can have disastrous consequences.
C++/CLI classes automatically implement IDisposable when adding a destructor, so in C# you'll need to either implement that interface or override the Dispose method if it's available in the base class.
Other tips:
If you need to call Win32 functions, just use P/Invoke instead of creating a C++/CLI wrapper
For complex native C++ code, better create a C++/CLI project with managed wrappers
Again, pay attention to pointers. I had forgotten to do Marshal.StructureToPtr in my P/Invoke code which wasn't necessary in the C++ version since we had the actual pointer and not a copy of its data.
I have surely missed some things, but hopefully these tips will be of some help to people who are demoralized by the amount of code that needs to be ported, especially in a short period of time :)
After porting is done, use VS/ReSharper to refactor and clean up the code. Not only is it nice for readability, which is my top priority when writing code, but it also forces you to interact with the code and possibly find bugs that you otherwise would have missed.
Oh and one final FYI that could save you headaches: If you create a C++/CLI wrapper that exposes the native C++ pointer, and need to use that pointer in an external C++/CLI assembly, you MUST make the native type public by using #pragma make_public or else you'll get linker errors:
// put this at the top of the wrapper class, after includes
#pragma make_public(SomeNamespace::NativeCppClass)
If you find a bug in the C++/CLI code, keep it. You want to port the code, not fix the code, so keep things in scope!
For those wondering, we got maybe around 10 regressions after the port. Half were mistakes because I was already on autopilot mode and didn't pay attention to what I was doing.
Happy porting!
Back ~2004 Microsoft did have a tool that would convert managed C++ to C++/CLI ... sort of. We ran it on a couple of projects, but to be honest the amount of work left cleaning up the project was no less than the amount of work it would have been to do the conversion by hand in the first place. I don't think the tool ever made it out into a public release though (maybe for this reason).
I don't know which version of Visual Studio you are using, but we have managed C++ code that will not compile with Visual Studio 2005/2008 using the /clr:oldSyntax switch and we still have a relic VS 2003 around for it.
I don't know of any way of going from C++ to C# in a useful way ... you could try round tripping it through reflector :)
Such projects are often done in c++/cli because C# isn't really an elegant option for the task. e.g. if you have to interface with some native C++ libraries, or do very high performance stuff in low level C. So just make sure whoever chose c++/cli didn't have a good reason to do it before doing the switch.
Having said that, I'm highly skeptical there's something that does what you ask, for the simple reason that not all C++/cli code is translatable to C# (and probably vice versa too).

Categories