我有一个用C编写的DLL。我在这个dll中有一个函数,例如:
unsigned char DLL_EXPORT getTRK(char *XML, unsigned long *Len)
{
MessageBox(NULL, XML, "Dll message", MB_OK);
char s[] = "Some string";
XML = s;
return rand()%2;
}
我需要在dll中更改XML变量值并将此值传递给我的C#prog。我在C#上有下一个代码:
[DllImport("Some_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern byte getTRK(string XML, uint Len);
...
string xml = "123";
uint len = 0;
tbXml.Clear();
if (getTRK(xml, len) == 0)
{
tbXml.AppendText(xml);
}
else
{
tbXml.AppendText("Some error!");
}
我尝试过不同的方法,但没有任何方法可行。 我想在xml变量中输入我的c#prog值="一些字符串"。我怎么才能得到它? 如果我使用ref或者像这样:
[DllImport("Some_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern byte getTRK(ref string XML, ref uint Len);
...
string xml = "123";
uint len = 0;
tbXml.Clear();
if (getTRK(ref xml, ref len) == 0)
{
tbXml.AppendText(xml);
}
else
{
tbXml.AppendText("Some error!");
}
dll获取一些垃圾值,而不是" 123"。如果我这样做:
*XML = *s;
也没有任何反应。
答案 0 :(得分:2)
C#使用2字节字符串并相应地编组它们。 char *用于存储1字节字符串。 你必须在你的DllImport属性和usec wchar_t * strings中指定charset。
如果你需要将字符串存储在char *中,你可以编写一个自定义marshaller,就像这样称为
void ErrorWriter([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string errorMessage, string taskId, ProcessType processType);
并像这样实施
internal class Utf8Marshaler : ICustomMarshaler
{
private static Utf8Marshaler _staticInstance;
public IntPtr MarshalManagedToNative(object managedObj)
{
if (managedObj == null)
return IntPtr.Zero;
if (!(managedObj is string))
throw new MarshalDirectiveException(
"UTF8Marshaler must be used on a string.");
// not null terminated
byte[] strbuf = Encoding.UTF8.GetBytes((string) managedObj);
IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length+1);
Marshal.Copy(strbuf, 0, buffer, strbuf.Length);
// write the terminating null
Marshal.WriteByte(buffer + strbuf.Length, 0);
return buffer;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero)
return string.Empty;
int length = 1;
IntPtr offsetPtr = IntPtr.Add(pNativeData, 1);
while (Marshal.ReadByte(offsetPtr) != 0)
{
offsetPtr = IntPtr.Add(offsetPtr, 1);
length++;
}
byte[] strbuf = new byte[length];
Marshal.Copy(pNativeData, strbuf, 0, length);
string data = Encoding.UTF8.GetString(strbuf);
return data;
}
public void CleanUpNativeData(IntPtr pNativeData)
{
Marshal.FreeHGlobal(pNativeData);
}
public void CleanUpManagedData(object managedObj)
{
}
public int GetNativeDataSize()
{
return -1;
}
public static ICustomMarshaler GetInstance(string cookie)
{
if (_staticInstance == null)
{
return _staticInstance = new Utf8Marshaler();
}
return _staticInstance;
}
}