C# P/Invoke: Pointer to string as error message - c#

I am attempting to use llvmc as a C# library using P/Invokes(because I can't find any .NET bindings).
However, I've a problem. llvmc uses char** for error passing.
An example would be this:
char* error = NULL;
LLVMVerifyModule(PointerToSomeModule, LLVMAbortProcessAction, &error);
What should I do to allow this function to be used in C# code?
EDIT: The example I found also mentions this call:
LLVMDisposeMessage(error);
I just saw the answers and thought this could be an important detail.

A char** argument is troublesome, there is a memory management problem. If you declare the argument as "out string", the P/Invoke marshaller is going to try to free the pointer. That's very unlikely to work, it requires the string to be allocated with CoTaskMemAlloc().
The only other option you have to declare it as "out IntPtr" and marshal the string yourself with Marshal.PtrToStringAnsi(). That will work, beyond an unpluggable memory leak if LLVMC actually expects you to free the pointer. Call it a million times to verify that. There are a few odds that it won't blow since it is an error message, it might return a pointer to a string literal.
The only option left then is to write a wrapper in the C++/CLI language so you can free the pointer.

Take a look at the StringBuilder class. Or you can also simply declare the parameter as an integer out parameter and use Marshal.PtrToStringAnsi.

Related

C# Interop Marshaling behaviour for arrays seems inconsistent with documentation

I am currently writing a thin C# binding for OpenGL. I've just recently implemented the OpenGL GenVertexArrays function, which has the following signature:
OpenGL Documentation on glGenVertexArrays.
Essentially, you pass it an array in which to store generated object values for the vertex arrays created by OpenGL.
In order to create the binding, I use delegates as glGenVertexArrays is an OpenGL extension function, so I have to load it dynamically using wglGetProcAddress. The delegate signature I have defined in C# looks like this:
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void glGenVertexArrays(uint amount, uint[] array);
The function pointer is retrieved and converted to this delegate using Marshal.GetDelegateForFunctionPointer, like this:
IntPtr proc = wglGetProcAddress(name);
del = Marshal.GetDelegateForFunctionPointer(proc, delegateType);
Anyways, here's what bothers me:
In any official documentation I can find on default marshalling behaviour for reference types (which includes arrays), is this:
By default, reference types (classes, arrays, strings, and interfaces)
passed by value are marshaled as In parameters for performance
reasons. You do not see changes to these types unless you apply
InAttribute and OutAttribute (or just OutAttribute) to the method
parameter.
This is taken from this MSDN page: MSDN page on directional attributes
However, as can be seen from my delegate signatures, the [In] and [Out] directional attributes have not been used on the array of unsigned integers, meaning when I call this function I should actually not be able to see the generated object values which OpenGL should have stored in them. Except, I am. Using this signature, I can the following result when running the debugger:
As can be seen, the call absolutely did affect the array, even though I did not explicitly use the [Out] attribute. This is not, from what I understand, a result I should expect.
Does anyone know the reason behind this? I know it might seem as a minor deal, but I am very curious to know why this seems to break the default marshalling behaviour described by Microsoft. Is there some behind-the-scenes stuff going on when invoking delegates compared to pure platform invoke prototypes? Or am I misinterpreting the documentation?
[EDIT]
For anyone curious, the public method that invokes the delegate is defined on a static "GL" class, and is as followed:
public static void GenVertexArrays(uint amount, uint[] array)
{
InvokeExtensionFunction<glGenVertexArrays>()(amount, array);
}
It is not mentioned on the documentation page you linked, but there is another topic dedicated to the marshaling of arrays, where it says:
With pinning optimization, a blittable array can appear to operate as an In/Out parameter when interacting with objects in the same apartment.
Both conditions are met in your case: array of uint is blittable, and there is no machine-to-machine marshaling. It is still a good idea to declare it [Out], so your intention is documented within the code.
The documentation is correct in the general case. But uint is a bit special, it is a blittable type. An expensive word that means that the pinvoke marshaller does not have to do anything special to convert the array element values. An uint in C# is exactly the same type as an unsigned int in C. Not a coincidence at all, it is the kind of type that a processor can handle natively.
So the marshaller can simply pin the array and pass a pointer to the first array element as the second argument. Very fast, always what you want. And the function scribbles directly into the managed array, so copying the values back is not necessary. A bit dangerous too, you never ever want to lie about the amount argument, GC heap corruption is an excessively ugly bug to diagnose.
Most simple value types and structs of simple values types are blittable. bool is a notable exception. You'll otherwise never have to be sorry for using [Out] even if it is not necessary. The marshaller simply ignores it here.

What C# datatype should I use to interface with unmanaged type "char* &sResult"

I am writing a C# code, and there is a code that needs calling an unmanaged C++ library.
The signature in the library's header is like this
bool GetValueFromFile(char* sPathToFile, char* &sResult);
What signature should I translate this in C#? I tried:
bool GetValueFromFile(string filePath, ref string result)
But it does not work. There is no exception and the return value is true. But the string result stays null. It is the same for out string result or StringBuilder result.
I use Marshal.GetDelegateForFunctionPointer to get the function pointer as delegate.
You can handle a reference to a pointer pretty much like a pointer to a pointer, at least as far as P/Invoke is concerned.
I think you will probably need to use an IntPtr for the sResult parameter, along with either Marshal.PtrToStringAnsi() or Marshal.PtrToStringAuto(), but it's a bit difficult to say without knowing whether the C/C++ function allocates the string memory or not.
If it works, you will probably still need to free the memory (after getting the string) using Marshal.FreeCoTaskMem() or Marshal.FreeHGlobal(), but again this is impossible to know for sure without knowing what the C/C++ function does.
NOTE: If using an IntPtr to get an output value, you will need to use out result or ref result.
You'll need to pass a pointer by reference. Assuming that sResult is passed from native to managed, i.e. that it has out semantics, here's the signature:
bool GetValueFromFile(string filePath, out IntPtr result);
Once you've called this you will need to convert it to a string:
IntPtr resultPtr;
if (GetValueFromFile(filePath, out resultPtr))
string result = Marshal.PtrToStringAnsi(resultPtr);
It's not clear who is responsible for freeing the memory that the native code allocates. Presumably that is documented somewhere and you already know how to handle that issue.

C# Marshal byte[] to COM SAFEARRAY parameter with "ref object" signature

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.

Issue using __declspec(dllexport) signature declaration from C++ dll to call in C#

I´m trying to call a method that is in a C++ dll declarated as __declspec(dllexport) to use in C#, but I don´t know how to return a string value from C++ and how to declare the signature using DllImport in C#.
C++ code "VNVAPI.dll"
__declspec(dllexport) char * GetGpuName(int phyGPUid)
{
CNvidia * pInstance = CNvidia::GetInstance();
char szName[512]={0};
pInstance->GetGpuName(phyGPUid,szName,512);
return szName;
}
C# method signature:
[DllImport("VNVAPI.dll")]
public static extern char GetGpuName(int phyGPUid);
Error generated:
A call to PInvoke function
'Core!Core.Hardware.IO.NVAPI::GetGpuName'
has unbalanced the stack. This is
likely because the managed PInvoke
signature does not match the unmanaged
target signature. Check that the
calling convention and parameters of
the PInvoke signature match the target
unmanaged signature.
Thanks.
As has been pointed out by others you need to specify the C calling convention in your P/Invoke and also use string on the managed side to marshal the null terminated char*.
However you should rejig the C++ routine to take a char* as an input parameter, together with a buffer length parameter. You then write into this buffer in the native code. This avoids the current problem that the data, as you presently have the code, is returned from the stack which, of course, is unwound as the function returns.
The suggestion to use static will make this memory global and so avoid stack unwind problems, at the expense of thread safety. Yes it will likely work for this use case but its a bad habit to get into.
The error message might be confusing.
Without going into detail, try this:
static char szName[512]={0};
If you still get the error, the you need to specify the calling convention in the DllImport attribute.
Edit:
Also make the return type string for C# method declaration.
The error message suggests checking the calling convention. I suspect that the function is using C calling convention, which would explain the unbalanced stack. I would suggest that you specify the calling convention (as #leppi suggested) in your DllImport attribute. Like this:
[DllImport("VNVAPI.dll", CallingConvention=CallingConvention.Cdecl)]
According to the Strings samples, the return value should be string:
static extern string GetGpuName(int phyGPUid);

How do I read the fontName property of a IHTMLComputedStyle interface in C#?

Acoording to documentation, this property gives me a TCHAR, but when I see the source code, this is the declaration:
[DispId(1011)]
ushort fontName { get; }
Anyway, I don't know how to neither get a TCHAR from a ushort or get a string from a TCHAR. Anyone?
I see it, you've got a problem. The IDL declaration is
[propget, id(DISPID_IHTMLCOMPUTEDSTYLE_FONTNAME)] HRESULT fontName([retval, out] TCHAR * p);
Well, that's technically possible, the caller would have to pass a pointer to a buffer of TCHAR that's large enough to store the returned string. That is massively odd though, strings are almost always handled as BSTR in COM interfaces. TCHAR* would be an accident waiting to happen when the caller doesn't pass a buffer that's large enough. And TCHAR will be just plain wrong when the client program is compiled without UNICODE in effect.
This has to be a bug, it should have been BSTR*. Or TCHAR**, a bit of a long shot. Another thing that's really odd is that they assigned DispIDs to the methods but didn't inherit the interface from IDispatch. That's just plain pointless. I don't think this was written by a MSFT programmer that knew what he was doing.
The type library importer would indeed have no choice but to pick ushort as the return type, there is no way for it to guess that it is actually an array of characters. There's is no MIDL attribute on the argument that says it is an array, another thing that's really odd and hinting that the argument really is a BSTR*. Patching the import library is technically possible, you'd have to decompile it, edit the .il and put it back together with ilasm.exe. Of course, you cannot really do this to the standard PIA, you'd have to give up on that.
No happy answers here, this is just plain wrong. Perhaps you can ping connect.microsoft.com to see what they think about it. Although they are liable to close it as "external", in which case Microsoft Support is your only real recourse.

Categories

Resources