I have a custom struct defined in MIDL:
struct Foo
{
[string] char* Bar;
int Baz;
}
I'm trying to pass this from a C# application to a C++ application. The interface assembly was generated with tlbimp.exe.
I should mention that I have next to no knowledge of MIDL and COM interop, but we're stuck using this interop method for the time being, so there's no way around that for now.
I tried various ways of defining an array of such a type, none with success. Ideally I'd want to call it on the C# side just like this:
ComObject.SomeFunction(someArray);
However, I may not be able to do that without a size parameter, so this would also be fine:
ComObject.SomeFunction(someArray.Length, someArray);
I tried the following ways to define it, none of which were successful:
HRESULT SomeFunction(struct Foo array[]); // For some reason it interprets this as a
// ref parameter... I assume because it's
// equivalent to a pointer?
HRESULT SomeFunction(struct Foo** array); // Tried with a pointer as well,
// but I think the memory layout messes it up
HRESULT SomeFunction(int length, [size_is(length)] struct Foo array[]);
HRESULT SomeFunction(int length, [size_is(length)] struct Foo** array); // I don't know how
// to marshal that on
// the C# side
What's the right way to define this in the MIDL and to invoke it on the C# side? Ugly temporary solutions welcome, since this entire thing will be refactored anyway in two months, but we need this before then. For example, currently I'm considering passing in two arrays of simple types (char* and int) and then combine them into the appropriate structure on the C++ side.
Related
I have been trying to create a handle to a structure type because I need a pinned pointer to it, but I am getting the error "Object contains non-primitive or non-blittable data"
My structure looks like this:
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
[MarshalAs(UnmanagedType.U1)]
public bool Test;
}
Now, when I call,
var mystruct = new MyStruct();
var handle = GCHandle.Alloc(mystruct, GCHandleType.Pinned);
I get the error "Object contains non-primitive or non-blittable data". Now I understand that the bool field is a non-blittable type. But I was under the impression that by adding the MarshalAs attribute, I could tell the marshaller how to convert the type. (I also tried UnmanagedType.Bool)
This structure has to be defined globally, because it is needed throughout my class. The only reason I need the pointer is because I have an unmanaged API that must pass this structure as a pointer. Then I have to get that structure in a callback and read/update members.
So this is the basic scenario.
Structure is created globally in a managed class
Pointer to structure is obtained
Pointer to the structure is passed into the API
The API calls a static method callback where I then need to get my structure and read/update members.
I tried to use Marshal.StructureToPtr but this only creates a copy, so if in my managed class I update the member, when the callback is raised, the updated value is not there.
Does anyone know how I can get a pinned pointer to my structure so I can read/modify the public members and have them available in the callback?
Thanks
You've got more than one problem here. Using a struct is highly inadvisable. It will get boxed before the GCHandle.Alloc() call and that boxed object gets pinned. You cannot see any updates to it through your mystruct variable. Use a class instead.
And avoid bool, it is a non-blittable type due to its highly variable implementation. It is 4 bytes in C, 1 byte in C++, 2 bytes in COM. Just make it a byte instead. You can write a property to get it back to a bool.
So:
[StructLayout(LayoutKind.Sequential)]
public class MyStruct
{
private byte _test;
public bool Test {
get { return _test != 0; }
set { _test = value ? 1 : 0; }
}
}
You're right that you're telling the marshaller how to marshal the type.
But that won't do you any good when you then attempt to bypass the marshaller.
You need to decide whether you want to use the marshaller, or whether you want the unmanaged code to directly write into managed memory.
If you want to use the marshaller:
Generally, a good way to handle this is to use it in both directions. You can use Marshal.StructureToPtr (as you've found), call the external function, and then use Marshal.PtrToStructure to convert it back into your managed representation.
Or you can use methods that are set up in such a way that marshalling happens automatically, without you needing to specify this manually. For example, calling a native method taking a ref MyStruct parameter will allow for that to happen.
If you don't want to use the marshaller:
Don't use any types that require marshalling. As Hans Passant comments, use a different type instead, byte would probably be a good choice.
(I'll refrain from commenting on the advantages and disadvantages of using structs here, except that the points already made about it are well worth reading and understanding.)
I have created a simple COM component in C++ and added a method like this
interface IMathControl : IDispatch{
HRESULT AddTwoNumbers(
[in] DWORD Number1,
[in] DWORD Number2,
[out] DWORD *pResult
);
};
I have consumed above component in my C# application and it works fine.
Now, I have a struct defined in C++ as this
struct AttributeValueInfo
{
string attribute;
string value;
string description;
};
My questions are:
How I can define a method which should return the result of AttributeValueInfo type in my C++ COM component ?
How I will consume that resultant struct AttributeValueInfo in my C# application ?
I think i need to do marshaling but don't know where to start. Can someone point the steps or a simple code snippet for above scenario.
Any help will be appreciated.
That is not possible. Only a C++ compiler can ever generate code to properly read the value of an std::string. With the additional restriction that it is the exact same version of the compiler with the exact same settings and using the exact same memory allocator. Interop capabilities for standard C++ classes compare unfavorably to those of a stone brick. C++ doesn't have anything similar to the kind of VM guarantees you get in C#, ensuring that basic rules like object layout and allocation is guaranteed for any code that runs in the process.
You must use a string type that has interop guarantees. That's BSTR in COM, directly supported and assumed by the CLR.
Using structs is pretty troublesome as well, their layout are heavily dependent on compiler settings. A declaration of the struct must appear in the type library you author, the CLR will use the IRecordInfo interface to safely access the struct members. Otherwise the kind of restriction that disappears when you realize that a struct is equivalent to a class with nothing but properties.
I've been going round and round in circles on Google on this, and I can find all kinds of discussion, lots of suggestions, but nothing seems to work. I have an ActiveX component which takes an image as a byte array. When I do a TLB import, it comes in with this signature:
int HandleImage([MarshalAs(UnmanagedType.Struct)] ref object Bitmap);
How do I pass a byte[] to that?
There's another function which can return the data with a similar signature, and it works because I can pass "null" in. The type that comes back is a byte[1..size] (non-zero bounded byte[]). But even if I try to pass in what came back, it still gets a type mismatch exception.
More details:
I've been editing the method in the IDispatch interface signature (using ILSpy to extract the interface from the auto-generated interop assembly). I've tried just about every combination of the following, it always gets Type mismatch exception:
Adding and removing the "ref"
Changing the parameter datatype to "byte[]" or "Array"
Marshalling as [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)]. After playing around with MarshalAs quite a bit, I'm becoming convinced that IDispatch does not use those attributes.
Also tried using the "ref object" interface as is, and passing it different types: byte[], Array.CreateInstance(typeof(byte) (which I think are both identical, but I found someone suggesting it, so it couldn't hurt to try).
Here's an example of Delphi code that creates a proper array to pass in:
var
image: OLEVariant;
buf: Pointer;
image := VarArrayCreate([0, Stream.Size], VarByte);
Buf := VarArrayLock(image);
Stream.ReadBuffer(Buf^, Stream.Size);
VarArrayUnlock(image);
Here's the C code to do the same thing. I guess if I can't get it to work from C#, I can invoke it through managed C++, although I'd rather have everything in one project:
long HandleImage(unsigned char* Bitmap, int Length)
{
VARIANT vBitmap;
VariantInit (&vBitmap);
VariantClear(&vBitmap);
SAFEARRAYBOUND bounds[1];
bounds[0].cElements = Length;
bounds[0].lLbound = 1;
SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds);
SafeArrayLock(arr);
memcpy(arr->pvData, Bitmap, Length);
SafeArrayUnlock(arr);
vBitmap.parray = arr;
vBitmap.vt = VT_ARRAY | VT_UI1;
long result;
static BYTE parms[] = VTS_PVARIANT;
InvokeHelper(0x5e, DISPATCH_METHOD, VT_I4, (void*)&result, parms,
&vBitmap);
SafeArrayDestroy(arr);
VariantClear(&vBitmap);
return result;
}
I finally figured out how to do it in 100% C# code. Apparently Microsoft never considered the idea that someone might use a method with this signature to pass data in, since it marshals correctly going the other direction (it properly comes back as a byte[]).
Also, ICustomMarshaler doesn't get called on IDispatch calls, it never hit the breakpoints in the custom marshaler (except the static method to get an instance of it).
The answer by Hans Passant in this question got me on the right track: Calling a member of IDispatch COM interface from C#
The copy of IDispatch there doesn't contain the "Invoke" method on IUnknown, but it can be added to the interface, using types in System.Runtime.InteropServices.ComTypes as appropriate: http://msdn.microsoft.com/en-us/library/windows/desktop/ms221479%28v=vs.85%29.aspx
That means you get 100% control over marshaling arguments. Microsoft doesn't expose an implementation of the VARIANT structure, so you have to define your own: http://limbioliong.wordpress.com/2011/09/19/defining-a-variant-structure-in-managed-code-part-2/
The input parameters of Invoke are a variant array, so you have to marshal those to an unmanaged array, and there's a variant output parameter.
So now that we have a variant, what should it contain? This is where automatic marshaling falls down. Instead of directly embedding a pointer to the SAFEARRAY, it needs a pointer to another variant, and that variant should point to the SAFEARRAY.
You can build SAFEARRAYs via P/Invoking these methods: http://msdn.microsoft.com/en-us/library/windows/desktop/ms221145%28v=vs.85%29.aspx
So main variant should be VT_VARIANT | VT_BYREF, it should point to another variant VT_UI8 | VT_ARRAY, and that should point to a SAFEARRAY generated via SafeArrayCreate(). That outermost variant should then be copied into a block of memory, and its IntPtr sent to the Invoke method.
I am developing a C# application. Since I have some algorithms for least-squares fit in C/C++ that would be too cumbersome too translate, I have made the C++ code into a dll and then created a wrapper in C#.
In the C# code, I have defined a struct that is passed to the unmanaged C++ code as a pointer. The struct contains the initial guesstimates for the fitting functions, and it is also used to return the results of the fit.
It appears to me that you must define the struct in both the managed and the unmanaged code. However, someone using my source code in in the future might decide to change the fields of the struct in the C# application, without understanding that they also have to change the struct in the native code. This will result in a run-time error at best (and produce erroneous results at worse), but there will be no error message telling the developer / end user what is wrong.
From my understanding, it impossible to create a test in the unmanaged C++ DLL that checks if the struct contains the correct fields, but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?
Otherwise, what ways are there to reduce the risk that some careless programmer in the future causes run-time errors that are hard to detect?
Sample code:
//C++
struct InputOutputStruct {
double a,b,c;
}
extern "C" __declspec(dllexport) void DoSomethingToStruct(InputOutputStruct* s)
{
// ... algorithm
}
//C#
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct InputOutputStruct {
public double a,b,c;
}
[DllImport("CpluplusDll.dll")]
public static unsafe extern bool DoSomethingToStruct(InputOutputStruct* s);
class CSharpWrapper {
static void Main(string[] args)
{
InputOutputStruct s = new InputOutputStruct();
unsafe {
InputOutpustruct* sPtr = &s;
DoSomethingToStruct(sPtr);
s = *sPtr;
}
}
}
It appears to me that you must define the struct in both the managed
and the unmanaged code.
Not true. This is what C++/CLI was invented for- facilitate much easier interoperation with C++ and .NET.
but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?
I don't think so, because you always need to define the structs on the C# side.
Here are a solution which may work ( never tested ):
Give each struct which is shared a unique identifier on both sides ( GUID, Macros )
Create a reflection for C++ which contains informations about the the types which are used on C# and C++ side. This could be done by using macros.
Compare the C++ structs and the C# structs on startup by using the GUIDs, reflection and macros. You can also use sizeof to compare sizes first.
That could be a lot of work
When working on C++ side you still can make a lot of things wrong when you not know about the macros
faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(
faacEncHandle hEncoder);
I'm trying to come up with a simple wrapper for this C++ library; I've never done more than very simple p/invoke interop before - like one function call with primitive arguments.
So, given the above C++ function, for example, what should I do to deal with the return type, and parameter?
FAACAPI is defined as: #define FAACAPI __stdcall
faacEncConfigurationPtr is defined:
typedef struct faacEncConfiguration
{
int version;
char *name;
char *copyright;
unsigned int mpegVersion;
unsigned long bitRate;
unsigned int inputFormat;
int shortctl;
psymodellist_t *psymodellist;
int channel_map[64];
} faacEncConfiguration, *faacEncConfigurationPtr;
AFAIK this means that the return type of the function is a reference to this struct?
And faacEncHandle is:
typedef struct {
unsigned int numChannels;
unsigned long sampleRate;
...
SR_INFO *srInfo;
double *sampleBuff[MAX_CHANNELS];
...
double *freqBuff[MAX_CHANNELS];
double *overlapBuff[MAX_CHANNELS];
double *msSpectrum[MAX_CHANNELS];
CoderInfo coderInfo[MAX_CHANNELS];
ChannelInfo channelInfo[MAX_CHANNELS];
PsyInfo psyInfo[MAX_CHANNELS];
GlobalPsyInfo gpsyInfo;
faacEncConfiguration config;
psymodel_t *psymodel;
/* quantizer specific config */
AACQuantCfg aacquantCfg;
/* FFT Tables */
FFT_Tables fft_tables;
int bitDiff;
} faacEncStruct, *faacEncHandle;
So within that struct we see a lot of other types... hmm.
Essentially, I'm trying to figure out how to deal with these types in my managed wrapper?
Do I need to create versions of these types/structs, in C#? Something like this:
[StructLayout(LayoutKind.Sequential)]
struct faacEncConfiguration
{
uint useTns;
ulong bitRate;
...
}
If so then can the runtime automatically "map" these objects onto eachother?
And, would I have to create these "mapped" types for all the types in these return types/parameter type hierarchies, all the way down until I get to all primitives?
I know this is a broad topic, any advice on getting up-to-speed quickly on what I need to learn to make this happen would be very much appreciated! Thanks!
Your are on the right track with how you would need to create managed structures that represent unamanged structures for use with P/Invoke.
It is however not the best strategy for interop with unmanaged libraries, because using this API from C# would still feel like using a C API - create and initialise a structure, pass it to a function and get some other structure in return.
It is OK to use P/Invoke for an odd function call that is not otherwise exposed as .NET API, but for a full blown API wrapper I would highly recommend using managed C++(C++/CLI). It is absolutely unparalleled in creating unmanaged interop layers for .NET.
The biggest challenge would be to convert this essentially C interface into an object orientated interface where you call methods off objects, as opposed to calling global functions with structures of all-public members.
As you start writing elaborate structure graphs for P/Invoke you would yourself having to deal with quite a bit of "magic" that governs how managed primitive types convert to unmanaged types. Often, using incorrect types will cause a run-time error.
With managed C++ (IJW - It Just Works) you define managed structures, classes, interfaces in C++, which allows more natural use of the underlying library and a more native interface to your C# application.
This is a great overview of C++/CLI. Also MSDN has extensive documentation for all managed C++ features.
Yes, you would need to declare all these structures in c#. Be careful to declare members with correct sizes. For example, 'long' is 32-bit in C++, but 64-bit in C#. For a pointer or void* in C++, use IntPtr in C#, etc.