C#/C++ pInvoke tips - c#

Whats the best way to go about modifying a C++ program to be used with pInvoke from C#.NET CF?
I have a large C++ codebase which makes extensive use of STL. Namely iterators, container classes, and standard strings.
On top of this many lightweight classes are passed around by value.
I want to build a C# gui ontop of this codebase for windows mobile touch devices.
Is it worth it?
I have managed to get some examples working using pInvoke to call C++ code from C#.NET, but writing wrappers for every access point and for all the STL return types seems very daunting and ugly. Is there another way or am I somewhat stuffed?
BTW. Managed C++ is not an option becuase its not supported in any form by .NET CF.
--edit:
I have one specific question in regards to pinvoke.
Suppose you had a function returning a C++ string by value
std::string foo () {
return std::string ("Hi");
}
I understand that its not possible to call this function from C# using pinvoke because there is no way to marshall the STL string, but my problem is that I cannot even write a wrapper without allocating a new array becuase the std::string returned is not on the heap.
char* foo2 () {
return foo().c_str(); //Very bad
//the returned pointer is released when the std::string falls out of scope.
//and will be invalid before the caller is able to do anything with it.
}
So my problem is, how to wrap foo into a pInvoke suitable format without needing to re-allocate the whole string.
char* foo2 () {
std::string f = foo();
char* waste = new char[f.length()+1];
strcpy (waste, f.c_str());
return f;
}
The thought of doing the above for every point at which I need to return a std::string is enough to make me give up trying to use C#.

I would personally say it's worth it, but I agree with the other post that it's not easy.
Possible approaches may be:
C interface around the C++ and exposed as a DLL.
COM objects (altho WM does not support COM servers so you are forced to use in-proc servers, basically a DLL COM implementation). This would give you a more OO interface.
Background process exposing some sort of API. You could go down the "CE Services" modal or come up with your own API.
All are possible and have there pros and cons. Whatever you do, you can't use STL types in the interface. You have reduced to simple basic types that are easy to marshal between the processes. Since your talking about C#, then COM may be go as you can expose OO interface.
I would recommend trying to keep the interface between the two as simple as possible.

What you want to do is not easy at all. If you really wanted to do it, your best bet is to create some clean, C interfaces that wrap all of the C++ and STL stuff and pass around structures that can pass from .net to C nicely. Depending on how big of a codebase you have, it can be a very difficult task.
Sorry.

maybe you should write a com wrapper and then use .net tool that will automatically create c# assembly for you?

doesnt SWIG create a C-style wrapper for C++ for you? Like handing all the non-basics of complex c++ ? Correct me if i'm wrong because I'm in a similar situation, I want to wrap a very large and complex C++ api exposed in a dll..i need to avoid mangling and the non basic data types by writing a C-style wrapper to expose all the stuff before Pinvoking that and it is infeasible without automated tools given the size of the api and the complexity of the types and prototypes.

Related

Importing C++ custom library functions into C#

I currently have a large C++ library that I need to incorporate into a C# project. I was successful in using DllImport to get access to some functions from my library, like this:
[DllImport("MyLib.dll")]
public static extern int SampleFunction(string param);
However, I can't seem to figure out how to make it work for functions that either have a parameter or return type that is not defined within the dll itself (i.e., the code in the dll imports it from another file), such as this example function that takes in a list:
[DllImport("MyLib.dll")]
public static extern std::vector<MyClass> MyFunction(string param);
For std library functions, I know I can get the dll and import that in, but what about other classes like MyClass in the above example? Do I need to create a managed wrapper class in C++ for each of these classes, or is there another way to do this?
std::vector<MyClass>, or indeed any unmanaged C++ class, cannot be used for interop to C#. Indeed, even if you wished to consume this function from another unmanaged C++ module you'd have to make sure that you were using the same compiler and dynamic runtime as the DLL which exported the function.
You'll need to find some other way to implement this functionality. There are lots of different ways to do that.
You could expose a p/invoke interface to the functionality. That would likely involve declaring a struct to represent the data of your class, and serializing to and from that struct.
You might consider a COM interface but it won't offer great advantages over p/invoke. You'd still need to serialize your class.
A C++/CLI wrapper would be yet another option. You'd wrap the unmanaged class with a managed C++/CLI class, and then consume that from the C#.
If you need a custom class from a native lib, you'll probably need to export a type library or use managed C++ to write a wrapper. What you're effectively trying to do is marshal a piece of memory from native to managed and now have to deal with how the data type is marshaled.
If at all possible, I would actually recommend trying to do away with the marshaling as when it works it's fine, but when it breaks, it can be rage inducing to debug.
Regardless, I'm actually not sure if anything in the STL can be marshaled. At the very least, I have never seen it done. More times, I've had to do a conversion like so: How can I marshall a vector<int> from a C++ dll to a C# application?
If you want to marshal an actual class, the standard way I've done it up until now is through a type library: Import TLB into C#
Or by linking a native lib into a managed C++ class and then referencing the managed C++ dll into the C# project as a shim.
Beyond that, if you can convert the class to strict C-style functions and pass a struct around, that could allow you to just use pinvoke, this is no different from simply exporting a bunch of helper functions except you can marshal a struct representation back and forth: Marshal C++ struct array into C#

How can I call a function of a C++ DLL that accepts a parameter of type stringstream from C#?

I want to import an unmanaged C++ DLL and call a function that takes stringstream as a parameter. In C#, there is no stringstream class, so can anyone tell me how to call such a function from a C# program?
You should not expose templated objects via a DLL, period.
Templated objects (e.g. almost everything in std::) become inlined. So in this way, your DLL gets its own private copy of the implementation. The module calling your DLL will also get its own private implementation of stringstream. Passing between them means you are inadvertently weaving two unrelated implementations together. For many projects, if you are using the exact same build settings, it's probably no problem.
But even if you use the same compiler, and mix a release DLL with a debug EXE, you will find stack / heap corruption and other harder-to-find problems.
And that's only using your DLL from another unmanaged C++ exe/dll. Crossing then the lines to .NET is even more of a problem.
The solution is to change your DLL's interface to something that plays friendly across DLL bounds. Either COM (you could use IStream for example), or just a C-style interface like the winapi.
If you can modify the C++ dll, export a plain string version. Otherwise you have to build a managed C++ wrapper project, import the other C++ dll, export it as a managed function, and call that from your C# code. C++ interop really sucks.
I'm afraid that you're going to have to create your own StringStream class in C# in order to be able to consume the functions exported from that DLL. As you mentioned, the .NET Framework doesn't provide any similar class out of the box.
The easiest way is probably to wrap the StringBuilder class provided by the .NET Framework such that it can function as a stream. See this blog post for a further explanation and some sample code.
A similar question was also answered in MSDN Magazine: http://msdn.microsoft.com/en-us/magazine/cc163768.aspx. You might find some of the hints and/or sample code given there useful.
You are trying to bind native C++ code to managed code in C#. Best way of doing that in general is to introduce middle layer in managed C++ that will provide interface to calls from C#.
Create an Wrapper dll in c, or c++ that exposes an friendly call to that function. It's the better way.
for example an
BOOL getString(TCHAR * myreturnString, DWORD *size);

COM to .NET Interoperability

If you want to use a COM type in your C# code, the process is straight forward, right? You just need to use the type library importer and that's fine, but what if you don't have one and you can't take a look at the IDL file? You just have the COM DLL server.
As an example, try using the IActiveDesktop interface.
What's the approch used to solve this kind of problem?
There are two kinds of COM interfaces. The one you are familiar with are the ones that restrict themselves to a subset of the COM spec known as "OLE Automation". Also known as ActiveX before that term became associated with security disasters.
Automation compatible interfaces are easy to use from just about any language. They typically inherit from IDispatch, allowing them to be used from scripting languages. And limit themselves to using only automation compatible types for their method arguments. The simple stuff, comparable to the .NET value types, BSTR for strings, SAFEARRAY for arrays, VARIANT for untyped arguments, quite similar to .NET's System.Object.
Another feature they support well is type libraries, the equivalent of .NET metadata. Used by a compiler to know how to call the interface methods. The IDE uses a type library to automatically generate the interop library so you can directly create the wrapper class and call the methods from .NET code.
Well, that's the good news. The bad news is that there are lots of COM interfaces around that do not use the Automation restrictions. They typically inherit from IUnknown and use function arguments that don't marshal well. Like structures. One very large and visible component in Windows that is like this is the shell. Windows Explorer.
That's where IActiveDesktop fits in as well, it is a shell interface and inherits from IUnknown. It is declared in the ShlObj.h SDK header file, there is not even a IDL file for it. And consequently no way to get a type library with its definition. It uses incompatible argument types, like LPCWSTR (a raw pointer to a string) instead of BSTR. And structure pointers like LPCCOMPONENT and LPWALLPAPEROPT. The CLR interop support is powerless to marshal that properly.
Using the interface in C# is technically not impossible, but you have to redeclare the interface. Very carefully, getting it wrong is very easy to do. The fact that source code that already does this is very hard to find is a hint how difficult it is. This squarely falls in the 'not impossible, but what sane programmer wants to maintain code like this' category. The shell is the domain of unmanaged C++ code. And a crew of hardy programmers, because debugging shell extensions is quite painful.

How to access unmanaged data from C#

I have an unmanaged (C/C++) DLL which I need to call from a C# application.
The DLL call needs to return data (from a C++ class that is created by the DLL) to the C# application.
I have control over the DLL's exported function, so I can create a wrapper around the C++ class if necessary. I know how to access the DLL with p/Invoke, so I'm just looking for some guidance on how to return the data.
The data that is received from the DLL is a series of key-value pairs, so I was thinking about returning a JSON string and deserializing it to an object with Json.NET.
What is the preferred way to access this type of data from an unmanaged source from a C#/.NET application?
If you're able to modify the C++ DLL then C++/CLI could be cleanest. You'll be able to write a set of .NET wrapper classes directly in C++, avoiding the need to write separate P/Invoke declarations.
There is no real reason to add extra layers of serialization just to transfer code between managed and unmanaged applications. But if it would be simpler for your code and you aren't worried about performance than any way you can move data from one layer to another is perfectly fine.
If you want to try the PInvoke way here are a few resources from MSDN...
DllImportAttribute
Platform Invoke Tutorial

Calling C# From Unmanaged C++ Passing Or Returning "Complex" Types

I'm after help on how to use complex objects either as return values or passed as parameters to C# class methods exposed to unmanaged C++ as COM components
Here's why:
I'm working on a project where we have half a dozen unmanaged C++ applications that each directly access the same Microsoft SQL Server database. We want to be able to use MS-Sql/Oracle/MySql with minimum changes and we've decided to implement a business logic plus data layer exposed via WCF services to get the required flexibility.
This strategy hinges on being able to get the unmanaged C++ to interop with the WCF service. There are a number of ways to do this, but the strategy I want to follow is to create a C# assembly exposed as a COM component which will act as a bridge between C++ and the WCF layer. This C# assembly will be loaded into unmanaged C++ process as COM component.
The C# bridge assembly will contain a helper class which has a number of methods that describe the operations that were formerly expressed as direct sql or stored proc calls in the C++ code.
I have two problems to solve
1) For an INSERT, I need to pass an object representing the entity to be inserted. On the unmanaged C++ side, the I already know that one of the entities has about 40 properties which have to make it into SQL - I don't want a C# method with 40 parameters, I want to pass an object; I don't know how to marshal a C++ object via COM into C#, so I thought about defining a Stuct on the C# side and then make the Struct COM visible.
2) How to return the result of a "SELECT this, that, other, ... ". I've seen two examples. One returns a struct[] and another returns a single struct containing a string[] for each column field and an int count member describing the length of the other member arrays.
On the C# side, I think it will be a case of defining and exposing a number of request/response structs which will be used to pass data in/out. These structs will need to be decorated with attributes that cause their members not to "change position" as a result of optimization. And the struct members may need to be decorated with the attribute that hints to the marshaller how the member should be exposed in COM.
Then of course I'll have to work out how to instantiate and populate these structs as seen as COM objects from the unmanaged C++, then I'll have to pass them in method calls and process them as return values.
This is the most difficult part for me; I grok C++ and some MFC/ATL but COM under C++ is a whole extra level of complexity. Any recommended books, blogs, tutorials on the subject of parameter passing and return value processing as I've described would be very helpful indeed.
If possible, I'd avoing bringing COM into the picture. If you control the C++ code (it sounds like you do), it should be easier to add a single C++/CLI cpp file that calls into your C# code. C++/CLI can directly access and create managed and unmanaged types and copy between them.

Categories

Resources