tags:

views:

118

answers:

5

I'm attempting to consume a dll written in C++ from a C# application. I have 3rd party source code for the C++ dll (the Cyclone physics engine) and do not want to manually port it over to C#.

In the C++ project
I changed it to output a dll. I changed it to use the /clr flag. I changed it to use Multi-threaded Debug DLL (/MDd) because that was the only one compatible with /clr and also compiled.

In the C# project
I added a reference to the dll. I'm using the cyclone namespace.

At first there was absolutely nothing under the namespace. I think this is because in the C++ code, all classes were declared with no access modifiers and the default is private. So for the class "Particle" I changed the definition to:

public class Particle
{
//...
}

Now I can successfully declare a variable of type Particle from the C# code. However, intellesense and the object browser report Particle to be a struct (?) and it doesn't contain any methods at all. The c++ code declares a bunch of methods after "public:" access modifiers so I don't know what the problem is.

For example,

public:
void integrate(real duration);

What am I doing wrong?

A: 

Try declaring the c++ class with the ref keyword:

public ref class Particle
AaronLS
245 compile errors when I add that one little keyword to the Particle class... Perhaps it isn't possible to use the clr option unless it was specifically written for it? I know this code was written as a pure c++ library without any thought given to .NET
colithium
For something like that I would create a wrapper "ParticleBridge" class that encapsulates the Particle class. Leave the original code as is so that it compiles successfully, and in your new ParticleBridge have a private member of a Particle instance, so that functions called on ParticleBridge will in turn call the function of that Particle. You will need to do some reading up on how to handle managed types and pointers from C++/CLI.
AaronLS
A: 

Do you have a reference to COM Interop?

Soppus
I thought when you specified the /clr flag it played nicely with .NET apps and you didn't need to use Interop. At least that's what I gleaned when researching if. But to answer your question: I don't think so
colithium
The reason I ask is that with most of the C++ dll's I have used, I have used a COM interface.
Soppus
+1  A: 

I have not actually run into your exact problem before, but I have used C++ dlls in c# before. Typically when calling a dll like that you would use the dllImport keyword. Basically you can define a class that imports all the types and methods from the c++ dll. You can then call those wrapper classes.

I am far from an expert on it, but I have used it to get access to win32 methods and some other libraries that I needed to use.

This link on codeplex has a few links tools that might help. But the most important is probably the Interop Assistant. It can generate the C# wrappers for your c++ dll.

This isn't exactly what you are asking, but I thought it might help to look at a different direction.

Glenn Condron
I've never heard of that tool, that should help a lot. I was kinda hoping the \clr flag was magic... :-/
colithium
+2  A: 

The Particle class is not a managed class, hence it is treated as a struct. You need to use the ref keyword to make it managed and garbage collected. You also need to do the same to every other class that references it which might be a problem. The best solution I think, is to create a managed wrapper class that uses the Particle class internally. This wrapper class can then be referenced by .net.

See here:

johannesg
Thank you, keeping the differences between C# and C++ straight is really hard for me for some reason...Would the P/Invoke Interop Assistant tool referenced by Caelum be able to generate a wrapper automatically? Or are there other tools that can accomplish this?
colithium
P/Invoke is a way to call native code that is not compiled with /clr. You still wont be able to instantiate the class, you can only call functions. Another approach can be to leave the dll as is and create a new managed c++ dll. This contains a managed api, designed to be easy to use from .net. The implementation then calls into the native dll. You should easily find working examples on the net.
johannesg