Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Friday, August 18, 2017 9:50 AM
I need to use OpenCL in my C# application. Looking into different ways of using C++ code in C# application I found these two solutions:
- Make a DLL with my C++ functions like this:
extern "C++"
{
__declspec(dllexport) void foo(){}
}
And then use them in my C# code like this:
using System;
using System.Runtime.InteropServices;
class HelloWorld
{
[DllImport("My.dll")]
public static extern void foo ();
}
This approach seems pretty straightforward, though I'm yet too look into using more complex objects as parameters (I am likely to need to pass large arrays of 2d points and matrices).
- Another option is involves making a DLL with my C++ code, then writing a C++/CLI wrapper for it and then using it in my C# code. Seems less straightforward, as it add an extra layer between my C++ and C# code and would also require the knowledge of C++/CLI.
Can someone explain me these two options? Which one would give better perfomance? What are the limitations of both?
All replies (2)
Friday, August 18, 2017 2:12 PM
1. You'd need to use extern "C" in your DLL. This would expose the DLL as a C export without the name mangling that C++ does. The resulting function would be something like _foo. In your DllImport you'd then need to specify the EntryPoint attribute and set the method name accordingly.
This is the way to go if you need access to a couple of functions in C++. The biggest restriction is that you cannot pass objects back and forth. This includes things from the STL, C++ strings or even other C++ classes. All these would have to be marshalled as pointers which makes for a confusing function interface and may even cause corruption.
2. C++/CLI is the better approach if you're dealing with C++ classes. You cannot easily pass class instances around using the extern "C" approach so simply wrapping it in C++/CLI makes the most sense.
The biggest benefit of this approach is that you can expose only the parts you actually need and you can store the native stuff in fields to avoid having to share them with managed code. This is especially important if you are dealing with lots of objects as fields. The disadvantage is that any objects that you do need to expose still either needs to be a pointer or you have to convert them to C++/CLI as well. Depending upon how much of that you have to do determines how big an effort it is.
There are many C++ functions that follow "object" semantics but aren't actually C++ classes. For example the standard HFILE in Windows follows this approach. While not a C++ class you do need to "initialize" it, track the handle and eventually close it. All of this screams out writing a C# class to wrap it. That is how a lot of the early framework worked. But ultimately this code is still extern "C" because that is how it is exposed by Win32.
As for performance I don't know that you can know without testing. I suspect that (1) is faster once the DLL is loaded simply because you're just marshaling data back and forth. But if you're wrapping one of those "object" semantic functions then you're going to be passing similar data back and forth each time. In this case (1) may start adding overhead vs just having C++/CLI keep a field internally that doesn't need to be passed back and forth. And if it is "object" semantics then you're writing a C# class anyway so it probably makes more sense to write the class in C++/CLI. That will allow you to mix C++/managed code in a single code base without the need for explicit marshalling. The generated code will handle it.
As for the learning curve, yes, you have to know C++/CLI but it really isn't too much of a stretch from C++ code or any # of the existing "extensions" added to C++. And presumably you'd be creating a standalone project in C++/CLI to wrap only the parts you want exposed so everybody doesn't necessarily need to understand it unless they change something in the interface code.
I going to throw out an option 3 now.
3. Use an existing managed library that wraps openCL. There are already some available. Unless you really need to optimize it or have an issue with using third party code then letting someone else solve the problem for you is always a good choice.
Michael Taylor
http://www.michaeltaylorp3.net
Friday, August 18, 2017 7:57 PM
See Managed C++ Wrapper For Unmanaged Code for my article and sample of your second method. Note that very many developers say "DLL" but there are very many types of DLLs. It is better to say "Class Library" than "DLL" when you are actually referring to a Class Library project.
The following has probably already been said by CoolDadTx but I will say it my way.
Sure, a Native DLL solution might be easier but depending on how much you need to do it might be a hassle to convert data to/from C using C#. The advantage of a Class Library DLL is that your C# code does not need to do anything special for C. As has been said, the Native DLL interface would not be capable of using classes. A C++ client using a C++ DLL can interface using classes but a C# client can't use classes with a C++ DLL.
Sam Hobbs
SimpleSamples.Info