In the Compact Framework 3.5, I am attempting to call an ActiveX object that has an IDL function signature:
HRESULT MyFunc([out] SAFEARRAY(float) *var)
The Interop generation creates the msil
[out] class [mscorlib]System.Array& marshal( safearray float32)
Which seems reasonable enough, but I keep getting a "NotSupportedException". According to an article entitled "Interop: Common issues and debugging techniques" (I can't post more than one hyperlink, it's the first google result for that phrase), in the first bullet point under the "Marshaling" heading, the compact framework doesn't properly marshal SAFEARRAYs.
I have attempted to get around this problem, by manipulating the answer described in this MSDN forum post (Last entry describes his method): http://social.msdn.microsoft.com/forums/en-US/clr/thread/6641abfc-3a9c-4976-a523-43890b2b79a2/
So, I have created the following definition:
[StructLayout(LayoutKind.Sequential)]
struct SafeArray
{
public ushort dimensions; // Count of dimensions in the SAFEARRAY
public ushort features; // Flags to describe SAFEARRAY usage
public uint elementSize; // Size of an array element
public uint locks; // Number of times locked without unlocking
public IntPtr dataPtr; // Pointer to the array data
public uint elementCount; // Element count for first (only) dimension
public int lowerBound; // Lower bound for first (only) dimension
}
And redefined the IDL for the function signature to:
HRESULT MyFunc([out] long *var)
And then issuing the following code:
IntPtr safeArrayPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(SafeArray)));
SafeArray safeArray;
safeArray.dimensions = 1;
safeArray.features = 0;
safeArray.elementSize = (uint)(Marshal.SizeOf(typeof(float)));
safeArray.locks = 0;
safeArray.elementCount = 6;
safeArray.lowerBound = 0;
safeArray.dataPtr = Marshal.AllocCoTaskMem((int)(safeArray.elementCount * safeArray.elementSize));
Marshal.StructureToPtr(safeArray, safeArrayPtr, false);
int iTmp = safeArrayPtr.ToInt32();
MyFunc(out iTmp)
While the code appears to succeed, when I try to read back the data values, using the Marshal.Copy(dataPtr, myFloatArr, false) function, I am getting all 0's for the data, which tells me that the pointer that the ActiveX DLL is getting is probably totally bogus and it's off writing into oblivion.
Any suggestions as to what I may have messed up in these definitions, or suggestions for other ways of approaching this problem?
Thanks In Advance...
Well, I've solved this one.
Hopefully, my answer will help others who encounter the same problem. The problem that I was running into was that the [out] tag in a COM tlb declaration means that whatever I pass in will be overwritten with the object created inside the COM library. A rather complicated version of the classic (and very elementary problem) "Pass By Reference vs Pass By Value"
So, the correct marshaling is to use the definition of SafeArray that I posted above.
Don't touch the IDL signature itself - that's not a very clean way of doing it. Instead, use ildasm on the generated Interop library to modify the il from:
[out] class [mscorlib]System.Array& marshal( safearray float32)
to
[out] native int&
and then reassemble with ilasm which will produce a C# function signature
void MyFunc(out IntPtr var)
The calling code then becomes:
IntPtr ip;
SafeArray safeArray;
float []arrFloats;
MyFunc(out ip);
//Marshal the structure itself
Marshal.StructureToPtr(safeArray, ip, false);
//Marshal the data over to .NET
float []arrFloats = new float[safeArray.elementCount];
Marshal.Copy(safeArray.dataPtr, arrFloats, 0, (int)safeArray.elementCount);
Finally, we need to free the memory (remember, we changed the function signature so we're not giving .NET enough information to actually free the memory on its own.
//Don't forget to free both the structure and the object
Marshal.FreeCoTaskMem(safeArray.dataPtr);
Marshal.FreeCoTaskMem(ip);
Related
I've read the various MSDN pages on C++ Interop with P/Invoke here and here but I am still confused.
I have some large arrays of doubles that I need to get into native code, and some resulting arrays that need to get back. I do not know the sizes of the output arrays in advance. For simplicity, I will use only a single array in the example. The platform is x64; I read that marshalling internals are quite different between 32- and 64-bit environments so this might be important.
C#
[DllImport("NativeLib.dll")]
public static extern void ComputeSomething(double[] inputs, int inlen,
[Out] out IntPtr outputs, [Out] out int outlen);
[DllImport("NativeLib.dll")]
public static extern void FreeArray(IntPtr outputs);
public void Compute(double[] inputs, out double[] outputs)
{
IntPtr output_ptr;
int outlen;
ComputeSomething(inputs, inputs.Length, out output_ptr, out outlen);
outputs = new double[outlen];
Marshal.Copy(output_ptr, outputs, 0, outlen);
FreeArray(output_ptr);
}
C++
extern "C"
{
void ComputeSomething(double* inputs, int input_length,
double** outputs, int* output_length)
{
//...
*output_length = ...;
*outputs = new double[output_length];
//...
}
void FreeArray(double* outputs)
{
delete[] outputs;
}
}
It works, that is, I can read out the doubles I wrote into the array on the C++ side. However, I wonder:
Is this really the right way to use P/Invoke?
Aren't my signatures needlessly complicated?
Can P/Invoke be used more efficiently to solve this problem?
I believe I read that marshalling for single dimensional arrays of built-in types can be avoided. Is there a way around Marshal.Copy?
Note that we have a working C++/Cli version, but there are some problems related to local statics in third-party library code that lead to crashes. Microsoft marked this issue as WONTFIX, which is why I am looking for alternatives.
It is okayish. The complete lack of a way to return an error code is pretty bad, that's going to hurt when the arrays are large and the program runs out of memory. The hard crash you get is pretty undiagnosable.
The need to copy the arrays and to explicitly release them doesn't win any prizes of course. You solve that by letting the caller pass a pointer to its own array and you just write the elements. You however need a protocol to let the caller figure out how large the array needs to be, that is going to require calling the method twice. The first call returns the required size, the second call gets the job done.
A boilerplate example would be:
[DllImport("foo.dll")]
private static int ReturnData(double[] data, ref int dataLength);
And a sample usage:
int len = 0;
double[] data = null;
int err = ReturnData(data, ref len);
if (err == ERROR_MORE_DATA) { // NOTE: expected
data = new double[len];
err = ReturnData(data, len);
}
No need to copy, no need to release memory, good thing. The native code can corrupt the GC heap if it doesn't pay attention to the passed len, not such a good thing. But of course easy to avoid.
If it were practical to separate the code that determines the output length from the code that populates the output then you could:
Export a function that returned the output length.
Call that from the C# code and then allocate the output buffer.
Call the unmanaged code again, this time asking it to populate the output buffer.
But I'm assuming that you have rejected this option because it is impractical. In which case your code is a perfectly reasonable way to solve your problem. In fact I would say that you've done a very good job.
The code will work just the same in x86 once you fix the calling convention mismatch. On the C++ side the calling convention is cdecl, but on the C# side it is stdcall. That doesn't matter on x64 since there is only one calling convention. But it would be a problem under x86.
Some comments:
You don't need to use [Out] as well as out. The latter implies the former.
You can avoid exporting the deallocator by allocating off a shared heap. For instance CoTaskMemAlloc on the C++ side, and then deallocate with Mashal.FreeCoTaskMem on the C# side.
If you knew the array size beforehand, you could write a C++/CLI DLL that takes the managed array as parameter, pins it, and calls the native C++ DLL on the pinned pointer it obtains.
But if it's output-only, I don't see any version without a copy. You can use a SAFEARRAY so P/Invoke does the copying instead of you, but that's all.
I'm currently trying to write a wrapper for a USB camera that uses an unmanaged C DLL to interface. The supplied software is written in C++ using Qt, and I'm trying to integrate this camera in a C# application I've already written (the application already uses a different camera that is supplied with a C# interface). I've read a bunch about unmanaged/managed interfacing, but I still am getting stuck with this specific DLL.
I'm having trouble dealing with P/Invoking the DLL. I've done a bunch of reading on ways to deal with managed/unmanaged code, and it seems that since I only have the functions/parameters (and nothing else), I can't write a C++/CLI wrapper and am forced to stick to P/Invoke. If this is untrue, some help with an alternate method would be appreciated, if more efficient.
Anyhow, I'm currently having trouble calling some (read: all) of the functions. For examples sake, let's pick this function (taken from dijSDK.h, the header file to be used when using this interface in unmanaged C++ in Qt):
/** \brief Find cameras currently connected to the host
*
* \param[out] pGuidList List of unique identifiers of connected cameras; memory is allocated by user
* \param[in,out] pNumGuids Pointer to the number of elements in pGuidList to limit the search
* \n Pointer to the number of cameras found
* \param[in] mask optional mask to limit the results in pGuidList
*
* \note
* - the function lists all supported cameras that are connected to the host having a driver installed
* - the cameras are identified by a string in a defined style:
* \n <i>[Name of the camera library resp. camera class]:[camera name]:[Serial number of the camera]</i>
* - the optional parameter mask may be used to limit the results returned in pGuidList;
* \n mask is in the same style as the results in pGuidList
* therefore the results can be limited to certain camera classes, camera types,
* and cameras with a given serial number */
DIJSDK_EXPORT error_t DijSDK_FindCameras(DijSDK_CamGuid* pGuidList, unsigned int* pNumGuids, const DijSDK_CamGuid mask = NULL);
DIJSDK_EXPORT is a define as follows:
#ifndef DIJSDK_EXPORT
#define DIJSDK_EXPORT externC DLLEXPORT
#endif
And the two typedefs used in the above function:
/// Return value of all DijSDK functions
/// \note All return values of type error_t can be casted to the enum <b>DijSDK_EErrorCodeList</b>, see header errorlistinstall.h
typedef int error_t;
// unique DijSDK types
/// Globally unique identifier for all supported cameras. It is used to establish a relation between <b>physical</b> and <b>logical</b> cameras.
typedef char DijSDK_CamGuid[64];
So looking at the function, the user passes in an allocated string array and the number of allocated strings in that array, and the function should return a bunch of strings and the number of strings it returns. I have absolutely no idea how to implement this in C#. I've tried different DllImport declarations of the function, like passing pGuidList as a...
StringBuilder
Where the variable I passed in was initialized with var = new StringBuilder(64) and the uint passed in was just 1.
StringBuilder[]
Where the variable I passed in was initialized with var = new StringBuilder[length], where length was the uint passed to the function.
IntPtr
Where the variable I passed in was initialized with Marshal.AllocCoTaskMem(64 * length * Marshal.SystemDefaultCharSize), where length is the same uint as above
And then passed in pNumGuids as ref uint. I don't hand in an argument for mask since it is optional, and I don't need to use it.
I constantly get a PInvokeStackImbalance since the signature of the managed import and the unmanaged DLL don't match, but I can't figure out what the correct signature is.
I've got questions about all of the functions I'm dealing with, but I'll be dealing with them one at a time. The first function I use is an "init" function that takes in a function pointer argument and a void pointer argument for a callback and it's associated data, but I can call it with no arguments if I don't need to use the callback and that is P/Invoking just fine. The function in this question is the one I need to call after to get a list of attached devices. I think if I can get this one working, I'll be able to figure out most of the rest of the functions.
The SDK and documentation I'm working with isn't publicly available online from the company that supplies it. If anyone would like it to see all of the code/documentation, I can post it on a fileserver and post a link to it.
Any help would be much appreciated! If there's anything that I left out, make sure to heckle me about it =P
Solution:
After the help, I managed to get it working:
The DllImport:
[DllImport(DLL,CallingConvention=CallingConvention.Cdecl)]
public static extern error_t DijSDK_FindCameras([Out] DijSDK_CamGuid[] pCamGuid, ref uint pNumGuids, string mask);
The struct to use for DijSDK_CamGuid:
[StructLayout(LayoutKind.Sequential,Size=64)]
public struct DijSDK_CamGuid
{
[MarshalAs(UnmanagedType.ByValArray,SizeConst=64)]
public char[] id;
}
And the findCameras() function:
private void findCameras()
{
uint cameralistlen = 5;
DijSDK_CamGuid[] cameralist = new DijSDK_CamGuid[cameralistlen];
result = Jenoptik.DijSDK_FindCameras(cameralist, ref cameralistlen, null);
}
Try declaring this way:
[DllImport("whatever.dll", CallingConvention = CallingConvention.Cdecl)]
extern public static int DijSDK_FindCameras(byte[] pGuidList, ref int pNumGuids, byte[] mask);
and using it like this:
byte[] CamGuids = new byte[64 * 32]; // Up to 32 cameras
int GuidsCount = CamGuids.Length / 64;
int result = DijSDK_FindCameras(CamGuids, ref GuidsCount, null);
Do you need to deal with the id in managed code as a string? If not, perhaps something like this would work, treating the bytes as an opaque byte array:
[StructLayout(LayoutKind.Sequential)]
public struct DijSDK_CamGuid
{
[MarshalAs(UnmanagedType.ByValAray,SizeConst=64)]
public byte[] id;
}
Then declare your p/invoke signature to use take a parameter of type:
DijSDK_CamGuid*
I have a C DLL which does some processing on an image and returns the result. So I am trying to pass an image over from the .NET side, but right now I am stuck, and I'm not sure whether that's on the types, the intricacies of marshaling, or syntax. Since I am a noob it could be all three.
I can call other functions in the DLL in question, so at least some of the foundations are in place. For example, when I call:
IntPtr versionIntPtr = GetDLLVersionNumber();
string version = Marshal.PtrToStringAnsi(versionIntPtr);
Console.WriteLine("DLL version number reported as: " + version);
and this works absolutely fine, printing the current version of the DLL to the console.
When I look at C code sample which uses the same function, it appears to use the function as follows:
unsigned char* ExtractImageInfo(const char* pixels, size_t width, size_t height)
(I also have a header file where the same function is mentioned as follows:
... ExtractImageInformation(struct ImageData image, void* imageInformation);
but I don't really know what this means.)
So my attempt to use this function goes as follows:
First I specify the interface to the DLL:
[DllImport("C:\\MyDLL", EntryPoint = "ExtractImageInfo", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ExtractImageInfo(IntPtr image, UInt32 imageWidth, UInt32 imageHeight);
Then, I get an image of the right type and get its dimensions:
Bitmap bitmap1 = (Bitmap)Image.FromFile("C:\\Images\\myImage.bmp");
UInt32 _imageWidth = Convert.ToUInt32(bitmap1.Width);
UInt32 _imageHeight = Convert.ToUInt32(bitmap1.Height);
Then I get a pointer to the image (since I think that's what I need to pass):
IntPtr bitmap1Ptr = bitmap1.GetHbitmap();
And then I call the function...
IntPtr myProcessedImage;
myProcessedImage = ExtractImageInfo(bitmap1Ptr, _imageWidth, _imageHeight);
But it doesn't work - I don't get back a pointer to my processed data. A big part of what I'm wondering here is whether I am passing the image in the right way, and whether the syntax for my interface to the native function is right. I think probably the answer to both could be NO!
I've only had a few days of reading and experimenting with PInvoke, so if anyone can point out to me the error of my ways I will be eternally grateful :-)
unsigned char* ExtractImageInfo(const char* pixels, size_t width, size_t height)
The name of the argument strongly suggests it wants a pointer to the raw pixel data. You can get one from Bitmap.LockBits(), BitmapData.Scan0 property. Don't call UnlockBits() until the function returns.
The return type of the function is a significant memory management problem. Whatever buffer pointer is returned is almost certainly going to have to be released. You cannot do so from managed code, you don't have access to the allocator used by this C code to call the proper version of free(). Call this function a million times and double-check that you don't have an out-of-control memory leak. If you do then you can't pinvoke it, a C++/CLI wrapper is required although the odds that it works correctly are fairly slim as well. This is a poorly designed function that's hard to use from any code, including C.
I'm calling C# method from C++ and passing char** as argument. It has to be char** because I need to return value through parameter.
C# code:
[ExportDll("test", System.Runtime.InteropServices.CallingConvention.StdCall)]
public static int test([MarshalAs(UnmanagedType.AnsiBStr)] ref string p)
{
Console.WriteLine(p);
}
C++ code to invoke function:
typedef int (__stdcall *MYPROC)(char **);
VOID main(VOID)
{
HINSTANCE hinstLib;
MYPROC MyProc;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
hinstLib = LoadLibrary(TEXT("mydll.dll"));
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "test");
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
char s1[] = "test";
char *s2 = s1;
char **s3 = &s2;
(MyProc) (s3);
cout << s3;
}
fFreeResult = FreeLibrary(hinstLib);
}
}
It's simple to pass char* (remove ref in c#, and use char* in c++), but when trying to pass char** i get a runtime error on line where I call the function :(
in c#, Console.WriteLine prints out correct value, but after that, I get an error:
Windows has triggered a breakpoint in COMDynamicLoad.exe.
This may be due to a corruption of the heap, which indicates a bug in COMDynamicLoad.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while COMDynamicLoad.exe has focus.
The output window may have more diagnostic information.
How should I do this?
You declare ref UnmanagedType.AnsiBStr but you expect a char**. This cannot work, since a ref to a BSTR is not a char**. See Default Marshaling for Strings for examples of marshaling declarations. These are possible declarations for an input-output string:
PassStringRef2([in, out] BSTR *s);
PassStringRef3([in, out] LPStr *s);
PassStringRef4([in, out] LPWStr *s);
and the equivalent C# marshaling declarations are:
PassStringRef2([MarshalAs(UnmanagedType.BStr)]ref String s);
PassStringRef3([MarshalAs(UnmanagedType.LPStr)]ref String s);
PassStringRef4([MarshalAs(UnmanagedType.LPWStr)]ref String s);
Your char** declaration is the equivalent of LPStr *s, so the correct marshaling is [MarshalAs(UnmanagedType.LPStr)]ref String s. But a better option is to use BSTR because of the explicit length declaration, and manipulate it in C++ with the BSTR helpers.
This is likely because you took a char* pointing to a string literal- which is bad because modifying that memory is undefined behaviour.
Would this work?
public static int test([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] p)
In many cases and as seems to be the situation here (see accepted answer by Remus Rusanu), using the proper marshaling attributes in the API declarations is all that is needed to have the interop "glue" on both ends of the interface start "playing nice with one another" and result in...
the proper data values being sent/delivered [good!]
Windows not triggering automatic breakpoint upon various suspected ... corruption of the heap ... [better! ;-)]
I am adding this answer, 5 months after the original post, because this question and its responses were very useful in fixing a recent interop bug of mine, but failed to mention directly information about the very plausible cause of many interop issues, namely:
Mismatch in the Memory Ownership conventions
(and/or in the memory allocation and freeing methods).
The January 2008 article on MSDN Magazine titled Marshaling between Managed and Unmanaged Code provided me with the info I needed in regards to memory ownership conventions. Indeed this article provides a complete overview of the marshaling process. It covers in specific details and examples the issues of
[InAttribute] and [OutAttribute] aka [In] and [Out]
Keywords Out and Ref and passing by reference
Return values
StringBuilder and marshaling
Copying and pinning
(Pinning = optiimization by CLR when it deems it safe to lock data area in the CLR heap and pass corresponding pointers to unmanaged code)
Memory Ownership:
No change allowed vs. In-place change vs. Reference change
Also, on the need of using CoTaskMemFree() and CoTaskMemAlloc() to free or allocate memory respectively received from or sent to the Managed code.
Reverse P/Invoke and delegate lifetime
P/Invoke Interop Assistant
This article is very useful because it gathers in a single document and in an accessible fashion information otherwise disseminated across dozen of technically authoritative but dry [and oft' confusing] reference documents (cf. the old but on-point joke about Microsoft's documentation at large).
In short, it makes it a good primer or refresher for casual implementers of interop solutions.
I have two unmanaged pointers in the form of IntPtr and want to copy data between them. How can I do this? I know the method Marshal.Copy, but it can only copy between unmanaged and managed.
And the second part: Is copying unmanaged data from C# slower than doing it in unmanaged C/C++ using memcpy?
Edit: I would be especially interested in a platform independet implementation.
You can use the win32 memcpy function via P-Invoke.
[DllImport("msvcrt.dll", SetLastError = false)]
static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count);
Apart from the (slight) overhead calling a win32 function from managed code, the actual copy performance should be the same as C/C++ code that uses the same function.
Don't forget that you can also use an unsafe block (and compiler option) and simply copy the data one byte/int/long at a time:
unsafe
{
// srcPtr and destPtr are IntPtr's pointing to valid memory locations
// size is the number of long (normally 4 bytes) to copy
long* src = (long*)srcPtr;
long* dest = (long*)destPtr;
for (int i = 0; i < size / sizeof(long); i++)
{
dest[i] = src[i];
}
}
This removes the platform dependency, but you need to be very careful with the bounds checking and pointer arithmetic.
Try System.Buffer.MemoryCopy, see the bottom of the page for supported target frameworks.
I believe that the main difference between this and the other solutions that use P/Invoke is that this method avoids the P/Invoke for smaller sizes and just does the copying directly.
Here's the guts of the implementation in .NET Core (latest as of 2020-09-04).
Without making comments on performance, purely because I have not tested it. You can achieve the same performance as unmanaged copy by using either CopyMemory or MoveMemory from Kernel32 via interop.
Here is the declaration for CopyMemory
[DllImport("kernel32.dll")]
static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
You could look at System.Runtime.CompilerServices.Unsafe.CopyBlock
It seems to allow you to copy bytes from the source address (designated by a void*) to the destination address (designated by a void*).
It also overriden to support ref byte as the source and destination.
[edit]
Disappointingly it appears not to be implemented in Mono
[edit] For those who are interested in this and using Unity, you should instead look to Unity's UnsafeUtility.MemCpy
CopyMemory aka RtlCopyMemory aka memcpy() will be just as fast whether called from C# or C (other than the tiny overhead of PInvoking the method itself).
Something to keep in mind, though, is that CopyMemory should only be used when you're sure that the source and destination ranges do not overlap. If they do overlap, you need to use MoveMemory instead, which will be slower.
Here is a declaration for CopyMeSomeMemory, showing how many different ways you can do the same thing in .Net:
[DllImport("kernel32.dll", EntryPoint = "RtlCopyMemory")]
public static extern void CopyMeSomeMemory(IntPtr Destination,
IntPtr Source, uint Length);
For the record, I think Buffer.BlockCopy in .Net just wraps one of these functions, too.