.NET Framework Bookmark and Share   
 index > Common Language Runtime > Marshal of C++ char[] to C# string
 

Marshal of C++ char[] to C# string


Hi guys,

this is my problem.
I have some C++ structure in unmanaged DLL. I need to use those structures in C#, in managed code.It seems all simple.... This is the C++ code of structures. Be careful to the structure "T__KRON_Struct_Error_Context" that is the structure that causes problems.

****************************

typedef char T__Char;
typedef unsigned __int32 T__UInt32;

typedef enum {
KRON_ERR_SUCCESS=1000,
KRON_ERR_RQC_DUPLICATED=1601,
KRON_ERR_RQC_BAD_CONF_FILE=1700,
}T__KRON_Returned_Codes;

typedef struct {
T__KRON_Returned_Codesm__errorcode;
T__Charm__errormessage[150];
T__Charm__errorfile[256];
T__UInt32m__errorline;
}T__KRON_Struct_Error_Context;


*****************************

My marshaling of structures in the C# Wrapper is the following:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
public struct T__KRON_Struct_Error_Context
{
public T__KRON_Returned_Codes m__errorcode;
/// T__Char[150]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 150)]
public string m__errormessage;
/// T__Char[256]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 256)]
public string m__errorfile;
/// T__UInt32->unsigned int
public uint m__errorline;
}


Now,the problem. From my managed code I call an unmanaged function, that i wrapped before. The signature of this function is

[DllImport(@"KRON.dll")]
public static extern T__KRON_Struct_Error_Context KRON_RecordQualityCheck(...some parameter...);


This unmanaged function would return the T__KRON_Struct_Error_Context, but if i call it, i obtain the well known exception "Method's type signature is not PInvoke compatible". THe problem IS NOT in the parameters that i pass to the function,the problem is in the T__KRON_Struct_Error_Context because if i change the marshaling of T__KRON_Struct_Error_Context in this way:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi )]
public struct T__KRON_Struct_Error_Context
{
public T__KRON_Returned_Codes m__errorcode;
public byte m__errormessageChar1;
public byte m__errormessageChar2;
public byte m__errormessageChar3;
(i could add until 150 declaration of single byte!)
};

so the call works and i'm able to read in the byte "m__errormessageChar1" the first character of the original m_errorMessage, in the byte "m__errormessageChar2" the second character and so on...without exception of "P/Invoke not compatible".

The question is: What is wrong in my marshaling? I tried also to replace the type "string" with "char[]" or "byte[]" or "StringBuilder" and a lot of others temptatives.....but nothing to do...It doesn't work.

Thanks in advance for your help.

Livio_75
There's nothing wrong with your P/Invoke declaration, you just hit a limitation in the marshaller. Your replacement works because it is blittable. You can't solve this easily, marshaling the return value yourself can't be done by the struct is passed by value. Maybe a custom marshaller, not so sure.

Best approach is to write a wrapper so the function signature changes to:

void KRON_RecordQualityCheck(..., T__KRON_Struct_Error_Context* error)


Hans Passant.
  • Marked As Answer byLivio_75 Monday, September 21, 2009 8:43 PM
  •  
nobugz
There's nothing wrong with your P/Invoke declaration, you just hit a limitation in the marshaller. Your replacement works because it is blittable. You can't solve this easily, marshaling the return value yourself can't be done by the struct is passed by value. Maybe a custom marshaller, not so sure.

Best approach is to write a wrapper so the function signature changes to:

void KRON_RecordQualityCheck(..., T__KRON_Struct_Error_Context* error)


Hans Passant.
  • Marked As Answer byLivio_75 Monday, September 21, 2009 8:43 PM
  •  
nobugz
THanks for your answer, Hans.
This isn't a good news....but at least i can stop to try hundred of calls. So the only way will be to create a C++ wrapper around the unmanaged DLL , and change the signature of this method. Then i could invoke "the wrapper of the wrapper".
Livio_75

You can use google to search for other answers

Custom Search

More Threads

• ProcessCreate(): CommandLine wth whitespace and quotes
• How to pass managed class reference through COM component to other managed code
• Access denied to .Net Framework
• AppVerifier returns "First chance access violation" When Calling System.ServiceProcess.ServiceController.GetServices()
• Certificate mapping to its private key
• Connection points in C#
• I need to call a .Net C# web service from a VB6 client
• Differences between using regasm and regasm /regfile to make an assembly COM visible
• How can get the target folder path from a shortcut
• How an assembly in VB can use in Visual C#