I have the following struct used in a C program
typedef enum { ndberror_st_success = 0, ndberror_st_temporary = 1, ndberror_st_permanent = 2, ndberror_st_unknown = 3 } ndberror_status_enum; typedef enum { ndberror_cl_none = 0, ndberror_cl_application = 1, ndberror_cl_no_data_found = 2, ndberror_cl_constraint_violation = 3, ndberror_cl_schema_error = 4, ndberror_cl_user_defined = 5, ndberror_cl_insufficient_space = 6, ndberror_cl_temporary_resource = 7, ndberror_cl_node_recovery = 8, ndberror_cl_overload = 9, ndberror_cl_timeout_expired = 10, ndberror_cl_unknown_result = 11, ndberror_cl_internal_error = 12, ndberror_cl_function_not_implemented = 13, ndberror_cl_unknown_error_code = 14, ndberror_cl_node_shutdown = 15, ndberror_cl_configuration = 16, ndberror_cl_schema_object_already_exists = 17, ndberror_cl_internal_temporary = 18 } ndberror_classification_enum; typedef struct { ndberror_status_enum status; ndberror_classification_enum classification; int code; int mysql_code; const char * message; char * details; } ndberror_struct; I need to marshal it in a c# program, the C# side declaration is:
public enum ndberror_status { ndberror_st_success = 0, ndberror_st_temporary = 1, ndberror_st_permanent = 2, ndberror_st_unknown = 3, } public enum ndberror_classification { ndberror_cl_none = 0, ndberror_cl_application = 1, ndberror_cl_no_data_found = 2, ndberror_cl_constraint_violation = 3, ndberror_cl_schema_error = 4, ndberror_cl_user_defined = 5, ndberror_cl_insufficient_space = 6, ndberror_cl_temporary_resource = 7, ndberror_cl_node_recovery = 8, ndberror_cl_overload = 9, ndberror_cl_timeout_expired = 10, ndberror_cl_unknown_result = 11, ndberror_cl_internal_error = 12, ndberror_cl_function_not_implemented = 13, ndberror_cl_unknown_error_code = 14, ndberror_cl_node_shutdown = 15, ndberror_cl_configuration = 16, ndberror_cl_schema_object_already_exists = 17, ndberror_cl_internal_temporary = 18, } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public struct ndberror_struct { public ndberror_status status; public ndberror_classification classification; public int code; public int mysql_code; [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string message; [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)] public string details; } The C-Side signature of the method to be called is:
const ndberror_struct __stdcall Ndb_getNdbError(void* obj); The C#-Side instead is:
[System.Runtime.InteropServices.DllImportAttribute("Ndb_CWrapper.dll", EntryPoint = "Ndb_getNdbError", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall,CharSet = CharSet.Ansi)] private static extern ndberror_struct Ndb_getNdbError(System.IntPtr obj); When i try to invoke the method from the managed code a MarshalDirectiveException raises. I think the problem is somewhere in the string marshalling, but i'm not able to solve the problem. The native library is compiled for a x64 system multibyte charset code (with visual studio c++ 2012)
The alternative can be some strange operation inside the native code, where i cast a NdbError (defined in another header) to ndberror_struct, here the code:
Ndb* tmp=(Ndb*)obj; ndberror_struct tmpRes=(ndberror_struct)tmp->getNdbError(); The NdbStruct returned by tmp->getNdbError() overload the casting operator (i suppose), this is the declaration:
operator ndberror_struct() const { ndberror_struct ndberror; ndberror.status = (ndberror_status_enum) status; ndberror.classification = (ndberror_classification_enum) classification; ndberror.code = code; ndberror.mysql_code = mysql_code; ndberror.message = message; ndberror.details = details; return ndberror; } Any help will be appreciated.
Edit: I tried to change a bit the method's signature in this way: C-Side:
void* __stdcall Ndb_getNdbError(void* obj) C#-Side:
IntPtr Ndb_getNdbError(IntPtr obj) the native method return &tmpRes and in the managed code i had marshalled manually the struct calling
var tmp=Ndb_getNdbError(raw); var f = (ndberror_struct)Marshal.PtrToStructure(tmp, typeof(ndberror_struct));
MarshalDirectiveException?