Creating Simple C++.Net Wrapper. Step-By-Step

Creating simple c++.net wrapper. Step-by-step

http://www.codeproject.com/KB/mcpp/quickcppcli.aspx#A8

This is general direction. You need to create C++/CLI Class Library project, add .NET class to it (StudentWrapper in this sample), create unmanaged class instance as managed class member, and wrap every unmanaged class function. Unmanaged library is added to C++/CLI project using linker dependencies list, and not as reference. In the Project - Properties - Linker open Additional Dependencies and add .lib name there.

Note: since we are talking about C++/CLI wrapper, no PInvoke! PInvoke is used to call exported functions (API), and not classes.

Creating .Net Wrappers for Windows API and COM DLLs

1) The windows API documentation includes the header, library, and dll file for each method/enum/etc. I just didn't scroll down far enough when I read through to notice this. A header file doesn't necessarily have to be in the same directory as the dll; its contents are simply copy/pasted into the .c file when the program is compiled. The part I was missing here was the linking stage of compilation which I read about here

2) The documentation was there--I just had to look for it a little bit harder.

3) How can I detect the type of a dll? (COM, .NET, WIN32)

4) The api for audio could theoretically span multiple dlls, so the best course of action is to find the API documentation, find the methods you want to wrap, then figure out what dlls those methods are in, and then import each of those DLLs.

Creating an C++/CLI OpenCV wrapper to use in C#

How I solved the problem with opencv using visual studio 2012:

  1. I created a c++ image processing library with opencv and compiled it to a static library (.lib) as mentioned here. Basically, create an console application project and change in Project configuration -> General -> Configuration type to a "static library (.lib)". That will compile your project to a .lib file which later you should use in c++/cli.
  2. Then i made a C++/CLI wrapper - for each class in c++ I was about to publish to c# I made a wrapper like in this link. I used existed headers from c++ just by adding to project like Add to project -> Existing Items and choose headers from project 1. This also have an advantage that if you change something in .lib file, you have the same .h files so when you recompile .lib, you don't have to change headers in c++/cli. I included .lib from 1. going to Project properties -> Linker -> Input -> Additional dependencies and put the path to the .lib file. This project was compiled to .dll file. (Project configuration -> General -> Configuration type -> "dynamic library (.dll)").
  3. In c# project I've just add to references the .dll and used classes from c++/cli , which are managed classes. And that is how magic works.

Remark A: I can assure that this solution worked. I used features like pattern detection and camshift with opencv 2.4.2.

Remark B: Another topic is how exactly marshalling should be made. In case of simple data types, there is no doubt in using c++/cli data types like UInt32 etc. But the question is if you want to pass more sophisticated objects like cv::Mat which do not have types direct equivalent in c++/cli. In that case, I made simplified version of such classes on c++/cli side.

Remark C: Don't mess architecture in different projects. If you are using e.g. x86, be consequent in all projects.

Remark D: Practically, the problem using c++ code in c# has two solutions: the one I described and the direct calling to c++ unmanaged code from c# managed code using dynamic on-the-fly marshalling. There are two major disadvantages: on-the-fly marshalling takes time and you do not really know how exactly do this between complex data types (namely, everything what is different than int or string). So c++/cli it is really a good option because you are able to mix managed and unmanaged code.

Remark E: This solution is general, it does not count only in opencv. I successfully used this making c++/cli wrappers to rotation stages (motor devices) which only have c++ drivers and used that drivers in c# code.

Regarding Remark C: Use a dependency walker like Depends (http://www.dependencywalker.com/) to see which dependencies are not consistent.

Wrapping C++ for use in C#

As a rule, the C/C++ structs are used for communicating with the native code, while you create CLI classes for communicating with the .NET code. C structs are "dumb" in that they can only store data. .NET programmers, on the other hand, expect their data-structures to be "smart". For example:

If I change the "height" parameter in a struct, I know that the height of the object won't actually change until I pass that struct to an update function. However, in C#, the common idiom is that values are represented as Properties, and updating the property will immediately make those changes "live".

That way I can do things like: myshape.dimensions.height = 15 and just expect it to "work".

To a certain extent, the structures you expose to the .NET developer (as classes) actually ARE the API, with the behaviors being mapped to properties and methods on those classes. While in C, the structures are simply used as variables passed to and from the functions that do the work. In other words, .NET is usually an object-oriented paradigm, while C is not. And a lot of C++ code is actually C with a few fancy bits thrown in for spice.

If you're writing translation layer between C and .NET, then a big part of your job is to devise the objects that will make up your new API and provide the translation to your underlying functionality. The structs in the C code aren't necessarily part of your new object hierarchy; they're just part of the C API.

edit to add:

Also to Consider

Also, you may want to re-consider your choice to use C++/CLI and consider C# and p/invoke instead. For various reasons, I once wrote a wrapper for OpenSSL using C++/CLI, and while it was impressive how easy it was to build and how seamless it worked, there were a few annoyances. Specifically, the bindings were tight, so every time the the parent project (OpenSSL) revved their library, I had to re-compile my wrapper to match. Also, my wrapper was forever tied to a specific architecture (either 64-bit or 32-bit) which also had to match the build architecture of the underlying library. You still get architecture issues with p/invoke, but they're a bit easier to handle. Also, C++/CLI doesn't play well with introspection tools like Reflector. And finally, the library you build isn't portable to Mono. I didn't think that would end up being an issue. But in the end, I had to start over from scratch and re-do the entire project in C# using p/invoke instead.

On the one hand, I'm glad I did the C++/CLI project because I learned a lot about working with managed and unmanaged code and memory all in one project. But on the other hand, it sure was a lot of time I could have spent on other things.

C++/CLI wrapper for native C++ to use as reference in C#

Ok, tutorial. You have a C++ class NativeClass that you want to expose to C#.

class NativeClass { 
public:
void Method();
};

1) Create a C++/CLI project. Link to your C++ library and headers.

2) Create a wrapper class that exposes the methods you want. Example:

#include "NativeClass.h"

public ref class NativeClassWrapper {
NativeClass* m_nativeClass;

public:
NativeClassWrapper() { m_nativeClass = new NativeClass(); }
~NativeClassWrapper() { this->!NativeClassWrapper(); }
!NativeClassWrapper() { delete m_nativeClass; }
void Method() {
m_nativeClass->Method();
}
};

3) Add a reference to your C++/CLI project in your C# project.

4) Use the wrapper type within a using statement:

using (var nativeObject = new NativeClassWrapper()) {
nativeObject.Method();
}

The using statement ensures Dispose() is called, which immediately runs the destructor and destroys the native object. You will otherwise have memory leaks and probably will die horribly (not you, the program). Note : The Dispose() method is magically created for you.

How can I build this simple C++/SWIG/C# project in Visual Studio 2010?

Step-by-Step instructions to completely build in the VS2010 IDE:

  1. Create a solution with two projects:
    • C# Console Application
    • C++ Win32 Console Application (Name=cpp, DLL, empty project). If you choose a different name, don't use the name of a class in your project and update the .i file %module name to match.
  2. Create a folder in the C# project called Generated.
  3. Add your .cpp, .h, and .i file to the DLL with the modifications below.

    • Note the whole class has to be exported. Replace <project> with the name of the project. There will be a preprocessor definition <project>_EXPORTS already defined for your DLL project (see Project, Properties, C++, Preprocessor).
    • The module name cannot match a class name in the module.
    • %include <windows.i> helps SWIG understand certain "Window-isms" like __declspec.

cpp_file.h

#pragma once

#ifdef <project>_EXPORTS
#define <project>_API __declspec(dllexport)
#else
#define <project>_API __declspec(dllimport)
#endif

class <project>_API cpp_file
{
public:
cpp_file(void);
~cpp_file(void);

int times2(int arg);
};

cpp_file.i

%module cpp

%{
#include "cpp_file.h"
%}

%include <windows.i>
%include "cpp_file.h"
  1. Select cpp_file.i, Properties, General, Item Type as Custom Build Tool.
  2. Select Apply to create the Custom Build Tool property group.
  3. In Custom Build Tool, General, Command Line enter:

    swig -csharp -c++ -outdir GeneratedFolderPath cpp_file.i
  4. In Outputs, enter cpp_file_wrap.cxx, and click OK to close the dialog.
  5. Right-click cpp_file.i and Compile. This should create four files: three in the C# Generated folder and one in the C++ project.
  6. Create a Generated Files filter in the C++ project and add cpp_file_wrap.cxx to it.
  7. Add the three Generated files to the C# project's Generated folder.
  8. Right-click the C# project and add the C++ project as a dependency.
  9. In the C# project's Properties, Build tab, change the Output Path from bin\Debug to ..\Debug or whatever the relative path to the C++ Project output directory is. The .exe and .dll need to be in the same directory.
  10. In the C# project's Main, add the lines:

    var cpp = new cpp_file();
    Console.WriteLine(cpp.times2(5));
  11. Build the solution.
  12. Run the C# project.

Good luck! Let me know if you get it to work. I can expand on anything unclear.

C# opensource djvu library

One of the most rated DjVU library is here:

DjVuLibre

However is in C++.



Related Topics



Leave a reply



Submit