简体   繁体   中英

How to convert a void* to a type that can be used in C#? Interoperability between C DLL and C#

I am a C/C++ programmer, but I was asked to update a program that was written in C# to communicate with a device. My knowledge of C# is very basic.

The previous version was totally written in C#, but now the API that in fact access the device was changed to C. I found out that I can import the C function APIs by using:

[DllImport("myapi.dll")]
public static extern int myfunct( 
                                 [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
                                 IntPtr hpDevice);

In C this function prototype is:

int myFunct( LPTStr lpDeviceName, HANDLE* hpDevice );

Where HANDLE is defined as :

typedef void *HANDLE;

However this function does not work as expected. In fact, in the C# code call what kind of type I should declare and pass to the C# method?

Thanks for the help and sorry for any stupid question.

Actually, this is the wrong way of marshalling HANDLE * . It'll work, but not be reliable in the face of exceptions.

The function you posted looks like an object creation function (it's treating hpDevice as an output parameter, and returning an int status result).

The correct way to marshal it depends on exactly what type of object it's creating and how it is closed. Assuming that the HANDLE is closed by calling CloseHandle (which is true for most but not all HANDLE objects), then you can probably use one of the types that inherits from SafeHandleZeroOrMinusOneIsInvalid . For example, if the object is a registry key, then use SafeRegistryHandle ; if it's a file, then use SafeFileHandle .

If it's some type for which there isn't an existing safe handle type (but does use CloseHandle to close it), then you'll have to define your own safe handle type derived from SafeHandleZeroOrMinusOneIsInvalid . If it's some type that doesn't use CloseHandle to close it, then you'll have to define your own safe handle type derived from SafeHandle .

Once you have determined the correct SafeHandle -derived type, then you can use it in the function call (using SafeFileHandle as an example):

[DllImport("myapi.dll")]
public static extern int myFunct(
    [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
    out SafeFileHandle hpDevice);

you are passing IntPtr instead of ref IntPtr, the definition should look like this:

[DllImport("myapi.dll")]
public static extern int myfunct( 
    [MarshalAs(UnmanagedType.LPTStr)] string lpDeviceName,
    ref IntPtr hpDevice);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM