Note that there are some explanatory texts on larger screens.

plurals
  1. POmarshalling a struct with char* to C#
    primarykey
    data
    text
    <p>I have the following struct used in a C program</p> <pre><code>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; </code></pre> <p>I need to marshal it in a c# program, the C# side declaration is:</p> <pre><code> 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; } </code></pre> <p>The C-Side signature of the method to be called is:</p> <pre><code>const ndberror_struct __stdcall Ndb_getNdbError(void* obj); </code></pre> <p>The C#-Side instead is:</p> <pre><code> [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); </code></pre> <p>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)</p> <p>The alternative can be some strange operation inside the native code, where i cast a <code>NdbError</code> (defined in another header) to <code>ndberror_struct</code>, here the code:</p> <pre><code>Ndb* tmp=(Ndb*)obj; ndberror_struct tmpRes=(ndberror_struct)tmp-&gt;getNdbError(); </code></pre> <p>The <code>NdbStruct</code> returned by <code>tmp-&gt;getNdbError()</code> overload the casting operator (i suppose), this is the declaration:</p> <pre><code>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; } </code></pre> <p>Any help will be appreciated.</p> <p>Edit: I tried to change a bit the method's signature in this way: C-Side:</p> <pre><code>void* __stdcall Ndb_getNdbError(void* obj) </code></pre> <p>C#-Side:</p> <pre><code>IntPtr Ndb_getNdbError(IntPtr obj) </code></pre> <p>the native method return <code>&amp;tmpRes</code> and in the managed code i had marshalled manually the struct calling</p> <pre><code>var tmp=Ndb_getNdbError(raw); var f = (ndberror_struct)Marshal.PtrToStructure(tmp, typeof(ndberror_struct)); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload