tags:

views:

96

answers:

3

Hello All, This question might seem a repeat of previous ones. I have read through a series of posts, but not completely clear for my situation.

I have a c++ library which is created using momentics IDE. I have to be able to use this library into a c# project.

Someone had been working on this project before being handed over to me. Currently, there are 2 layers for making this possible. First, a c++ project includes the complete library with a c++ wrapper. This project creates a dll as the output. This c++ dll is then fed to a c# project, which has dllimport calls to the c++ dll. This c# project again creates a dll. Finally, in order to use the library in c# application, I have to include a reference to both of these dlls.

Is this the correct way to get it working? I was thinking probably there should be a way to simplify the process.

Can someone please help me with this question?

A: 

You can use:

DllImport

class Example
{
    // Use DllImport to import the Win32 MessageBox function.
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

    static void Main()
    {
        // Call the MessageBox function using platform invoke.
        MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);
    }
}
Lukas Šalkauskas
+5  A: 

Given that you're using a C++ library, I'm assuming it takes advantage of C++ semantics like classes, rather than just exposing procedures. If this is the case, then the way this is typically done is via a manually-created managed C++ interop library.

Basically, you create a managed C++ library in Visual Studio, reference your existing C++ library, and create a managed wrapper around your existing C++ classes. You then reference this (managed) C++ assembly in your C# project and include the original (unmanaged) C++ library in your C# assembly just as a file that gets placed in the build directory.

This is required because there is no way to reference things like C++ classes via P/Invoke (DllImport) calls.

If your base library is just a series of functions, then you can reference that directly in the C# project via P/Invoke functions.

Either way, all of the libraries mentioned above (for the first, the unmanaged C++ library, the managed C++ assembly, and the C# project, or, for the second, the unmanaced C++ library and the C# project) must be included in any project that references them. You cannot statically link the unmanaged library into the managed assembly.

Adam Robinson
+1, but I'd like to point out that unless you're using .NET 1.1, "managed C++" is now called "C++/CLI", and there are *huge* differences between the two.
Randolpho
Also, I think you mean "you cannot dynamically link the unmanaged library". *Statically* linking is the only way to use the library.
Randolpho
Thank you so much.... As you mentioned, the unmanaged lib does have classes and interfaces. This being the case, I believe I have to have a c++ wrapper and a c# wrapper to be able to use the unmanaged c++ lib in my c# app, right? Now the c++ wrapper does the task of creating instance of the classes and implementing the interface, is that correct?I have another question. Is it the job of the unmanaged lib to provide extern "C" and _dllexport functionality? Currently it does not, but I can put that as a requirement for the next project, so just want to make sure.
Batul
@Batul: To your first question, yes; you'd need to create a wrapper class in C++/CLI (thanks to @Randolpho for the clarification of terminology) that consumes your classic C++ types. To your second question, yes, if you want to go the `DllImport` route, then your unmanaged library needs to expose `extern "C"` functions in order for them to be consumable in a fully managed (C#, VB.NET, etc.) assembly. Note here that we're talking about two different things; typically you *either* use the C++/CLI assembly as a wrapper *or* you export procedural functions and `DllImport` them in your managed code
Adam Robinson
Oh, the existing implementation uses both of these methods. The guy working on this before me has created a c++ wrapper and exported the functions. Then, he also uses DllImport in c# to access the functions. Thanks for the clarification. Now, considering that the unmanaged c++ lib has classes and interfaces, can DllImport be an option? Also, if I create c++/cli wrapper, then does it mean that I can simply add that as a reference in the c# app n use it as it is? without having to use DllImport? Im really sorry for asking so many questions, but thank you so much for your patience.
Batul
@Batul: There's no reason that you *can't* use both, it's just not a typical solution. And yes, if you create a C++/CLI wrapper, then you can simply add it as a reference in your C# assembly without any other work. The C++/CLI types will be available just the same as any other .NET type.
Adam Robinson
@Batul: Considering that I advocated the solution you've chosen (a C++/CLI wrapper) and gave an (IMO) more comprehensive explanation, I'm curious why you've "unaccepted" my answer and selected another that was later and has fewer votes?
Adam Robinson
Its not that, I assumed that once I select a post as an answer, it would carry fwd that one for all consecutive comments on that post, hence the confusion. As you mentioned, I realised your solution was the best one. Thanks a lot......
Batul
+2  A: 

Seems like you have one wrapper too many but perhaps someone is implementing some sort of facade or adding properties or something. The basic connection between managed and unmanaged will be either DllImport of "flat" function calls - not member functions - or C++/CLI code calling member functions. If the wrapper is C++/CLI it's easiest to write (just include the header for the C++ library) and easiest to call (C# code just adds a .NET reference to it and carries on as normal) so it would be my first choice if there's C++ expertise on the project.

It sounds like whoever you were taking over from is doing it the hard way. If there are less than 20 methods, I would suggest starting over.

Kate Gregory
Starting over looked like the best solution to me too, but once I started, whatever I looked at, only pointed out the current solution being the correct way to do it. What I understand from your suggestion is also to have a c++ wrapper to handle the classes in the unmanaged c++ lib, and then use dllImport calls in c#. Am I correct?
Batul
If you add a C++/CLI wrapper, it can save you from P/Invoke (DllImport.) Basically your C++/CLI code can just "include the header, link to the lib" to use your native code. Anything that is `public ref class Foo` in the C++/CLI code can be called from C# with no interop mechanism at all - just add a reference and use it.
Kate Gregory
Thanks Kate. From what I have read so far, DllImport requires a flat structure in the unmanaged lib, i.e. no classes and interfaces. But my unmanaged lib has classes and interfaces, so does that mean I cannot use DllImport? If so, then creating c++/cli wrapper is the only way to go?
Batul
In C++-land there is pretty much never an "only way to go". Just better ways. Writing a flat wrapper around your classes so you can use DllImport doesn't seem like a good plan. I would prefer the C++/CLI approach.
Kate Gregory