How to marshal a list in C# - c#

I have to send a list from C# to C++.The C# list is List<string>MyList and the C++ code accepts it as list<wstring>cppList.How to use marshalas for this.
Thanks

It is always wiser not to use complex type marshaling between native code and managed code.
In case of List, these type totally differ from each other as they have different memory layout for each item.
So the best way is to write a utility function in a native dll that accepts array of string(char*) and manually build your native List and ultimately call the desired method. It is easy for your to create wrapper of that utility function.

C# cannot P/Invoke complex C++ types. You will have to use C++/CLI, they might have a method for marshalling it across. Else, you will have to marshal each string across individually.

strings in C# are wstrings (2 byte unicode strings), so if what you say is true, then no special conversions are necessary.

Related

call C++ function which is having std::list as parameter

here i am writing wrapper to call c++ function in c# project.Here i am not using Dllimport method. I am looking C++/CLR approach. using C++/CLR approach we can add Dll directly to the c# project.
In my C++/CLR i have one function like below.
int StartScan(std::list<SomeObject*> *DeviceList);
i want call this function from C#. what's the equivalent property to call from C#.
i have tried with LinkedList which is equivalent property for std::list, if we used P/Invoke Approach.
You can't. Since your question implies that you are using C++/CLR and that you have control over that code, you should write the public method C# is supposed to use to take a managed List<T> object as the parameter, and then copy the contents to the std::list<SomeObject*> object that your C++ code apparently actually needs.
You'll need a managed type for T, something that is equivalent to the SomeObject you're using in C++. You'll have to clone those objects from the managed type to your std:list as well.
If you aren't able to change the C++/CLI code, then you'd have to write a shim DLL to handle the conversion. P/invoke doesn't know how to do this automatically.
If you are able to use the STL/CLR library, as recommended in this comment, i.e. you can switch your std:: library usages to the cliext:: library, then it includes code to help with this. For example, you can create a cliext::list object, pass your managed List<T> to its constructor, and it will copy the contents of your managed list to the cliext::list object.
For example: How to: Convert from a .NET Collection to a STL/CLR Container

Create COM interface returning a pointer that is marshalled as IntPtr in C#

I want to declare a COM Interface in MIDL that allows for returning a pointer (like in the ID3D11Blob). I understand that pointers are a special thing in COM because of the stubs generated for RPC calls. I do not need RPC, but only want to access the COM server from C#. The question is: can I declare the interface in such a way that the C# stub returns an IntPtr? I have tried to add [local] to enable void pointers, but that does not suffice.
The interface should look in MIDL like
[local] void *PeekData(void)
and in C# like
IntPtr PeekData()
Is this possible? If so, how?
Thanks in advance,
Christoph
Edit: To rephrase the question: Why is
HRESULT GetData([in, out, size_is(*size)] BYTE data[], [in, out] ULONG *size);
becoming
void GetData(ref byte, ref uint)
and how can I avoid the first parameter becoming a single byte in C#?
This goes wrong because you imported the COM server declarations from a type library. Type libraries were originally designed to support a sub-set of COM originally called "OLE Automation". Which restricts the kind of types you can use for method arguments. In particular, raw pointers are not permitted. An array must be declared as a SAFEARRAY. Which ensures that the caller can always index an array safely, safe arrays have extra metadata that describes the rank and the lower/upper bounds of the array.
The [size_is] attribute is only understood by MIDL, it is used to create the proxy and the stub for the interface. Knowing how many elements the array contains is also important when it needs to be copied into an interop packet that's sent on the wire to the stub.
Since type libraries don't support a declaration like this, the [size_is] attribute is stripped and the type library importer only sees BYTE*. Which is ambiguous, that can be a byte passed by reference or it can be a pointer to an array of bytes. The importer chooses the former since it has no hope of making an array work, it doesn't know the size of the array. So you get ref byte.
To fix this issue, you have to alter the import library so you can provide the proper declaration of the method. Which requires the [MarshalAs] attribute to declare the byte[] argument an LPArray with the SizeParamIndex property set so you can tell the CLR that the array size is determined by the size argument. There are two basic ways to go about it:
Decompile the interop library with ildasm.exe, modify the .il file and put it back together with ilasm.exe. You'd use a sample C# declaration that you look at with ildasm.exe to know how to edit the IL. This is the approach that Microsoft recommends.
Use a good decompiler that can decompile IL back to C#. Reflector and ILSpy are popular. Copy/paste the generated code into a source file of your project and edit the method, applying the [MarshalAs] attribute. Advantage is that editing is easier and you no longer have a dependency on the interop library anymore.
In either case, you want to make sure that the COM server is stable so you don't have to do this very often. If it is not then modifying the server itself is highly recommended, use a safe array.
I think I found the solution on http://msdn.microsoft.com/en-gb/library/z6cfh6e6(v=vs.110).aspx#cpcondefaultmarshalingforarraysanchor2: This is the default behaviour for C-style arrays. One can avoid that by using SAFEARRAYs.

How to pass C++/CX structs to pure C++ methods?

Say I have a legacy pure C++ library that contains a set of functions having C++ structs (native) as their parameters. This library is gonna be wrapped into a WinRT component that will be used from C# (platform - Windows Phone). Obviously, the most simple solution is to repeat all the structures as C++/CX value structs.
But how to pass these structs to pure C++ functions/methods ? Is it possible ?
If no, what is the solution wrapping the logic in this case?
In general, a value struct from C++/CX will require copying of some form in your C++/CX layer, before passing into the native code. You'll need to marshal the data from the C++/CX form into the native forms you are using.
That being said, the documentation does suggest that you can directly use memcpy to copy from a value struct to a standard (native) C++ struct, which would be cleaner than mapping the values individually, provided you don't use String^ or IBox<T>^:
A value class or value struct that contains a Platform::String^ or IBox^ type as a member is not memcpy-able.
Yes, it's possible. Read up about P/Invoke and structures. You'll have to replicate the structures and Function declarations in C#, but it generally works rather well. Check out the Docs to StructLayoutAttribute, DllImportAttribute and LayoutKind.

Passing buffer for recv() and send() from C# to C++

I have a C++/CLI wrapper for a C++ class which I create several instances of in a C# application, and this works fine, except for the functions in the C++ code which take a buffer from the calling function and fill it with whatever is received a call to recv, similarly some functions take a packet to be sent as a parameter.
In the C++ code there are several structs that define all the packet structures, pointers to which are taken as parameters, and I have equivalent C# structs which are packed in the same way so that they appear exactly the same in memory, what I don't know is what C++/CLI type I can use as parameters for functions that take pointers to C# structs, and can be passed to the C++ code.
Thanks.
You don't need any special “C++/CLI type”, you need just the C++ type. If it is a simple C-like struct (no virtual method tables or anything like that), then you could try using Marshal::StructureToPtr(). If it's not that simple, you probably need to copy it from the C# object field by field.

C#/C++ pInvoke tips

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.

Categories

Resources