简体   繁体   中英

c# P/Invoke : Pass Enum value with IntPtr to Function; AccessViolationException

I'm implementing C# wrapper to link C-library and having trouble passing Enum value as parameter to Unmanaged function call which takes pointer as input. that is throwing this exception. The code looks like this :

Function from library :

int function(infoField Field, void const *value); 

Marshal in C#:

[DllImport("CLibrary.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
static extern int function(infoField Field, IntPtr value);

infoField structure :

public enum infoField {section, options, orientation};

One Enum type 'Options' has 4 values to choose from :

public enum Options { var1, var2, var3, var4};

I want to pass one of the 4 choices as value for EnumField = Options, something like this:

IntPtr value = (Intptr)Options.var1;
function (infoField.options,  value);

I think I am missing correct cast convention for pointer to point to Enum type. What should be correct format to pass enum value with IntPtr to function? So far, I have tried few options but get AccessViolationException on function call, Which either means memory allocation failed or did not match what what library is expects the type.

PS : Function marshaling is successful for Other EnumFields. That's also because value passing is string value for them. But Particularly for 'options' it has to be one of 4 Enum options.

Normally, C++ enumerators are defined as follows:

enum class ENUM_FIELD
{ 
    VAR1, 
    VAR2,
    VAR3,
    VAR4
};

By default, enum class types are int sized, which means that you can translate them to C# as follows:

public enum EnumField
{ 
    VAR1, 
    VAR2,
    VAR3,
    VAR4
}

In such case, both enums will be mapped without problem within the interop environment. But if the C++ enum is defined in a different way, or if the unmanaged method requires a different type, you may need to change the underlying type in your C# declaration in order to map the values correctly. For example:

public enum EnumField : short
{ 
    VAR1, 
    VAR2,
    VAR3,
    VAR4
}

Anyway, I think the problem is not caused by the enum, but rather by what you pass as the const void* parameter. Casting an enum value to IntPtr doesn't look right to me:

UInt32 field = (UInt32)EnumField.VAR1;
GCHandle handle = GCHandle.Alloc(field, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();

// pass the ptr variable to the unmanaged function
// and don't forget to handle.Free() when you are done

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