我有来自c ++的以下签名
IDTECHREADER_EXPORTS void ReadTwoBlocks(char *pathConfig,
char *datablock1, char *datablock2, int timeout, bool &ret )
我能够在Full .NetFrameWork上正确编组,并且工作原理如下
[DllImport("IDTechReader.dll", EntryPoint = "ReadTwoBlocks" )]
private static extern void _ReadTwoBlocks(
[In][MarshalAs(UnmanagedType.LPStr)] string pathConfig,
[Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder datablock1,
[Out] [MarshalAs(UnmanagedType.LPStr)] StringBuilder datablock2,
int TimeOut,
ref bool result);
但是,如果使用与上面相同的Marshaling在NetcompactFramework(Windows CE)上不起作用,则会出现错误“NotSupported Exception”
我们如何正确地制作上述C ++方法签名,以便它在.NET CompactFramework(windows CE)上正常工作
任何想法都得到了回复......谢谢。
答案 0 :(得分:3)
编组人员可能会对MarshalAs(UnmanagedType.LPStr)感到窒息。您要么必须将签名更改为固定大小的byte []并使用Encoding.ASCII.GetString()在托管代码中进行字符串转换,要么可以使用IntPtr类型并使用Marshal.AllocHGlobal分配内存/ FreeHGlobal并处理代码中的字符串转换。
我认为这可能有用..
private const int MAX_STRING = 256;
[DllImport("IDTechReader.dll", EntryPoint = "ReadTwoBlocks")]
private static extern void _ReadTwoBlocks(
byte[] pathConfig,
[Out] byte[] datablock1,
[Out] byte[] datablock2,
int TimeOut,
ref bool result);
public void ReadTwoBlocks(string pathConfig,
StringBuilder datablock1,
StringBuilder datablock2,
int TimeOut,
ref bool result)
{
var pathConfigBuff = new byte[MAX_STRING];
var datablock1Buff = new byte[MAX_STRING];
var datablock2Buff = new byte[MAX_STRING];
// Convert unicode string to null terminated single byte charater string
Array.Copy(Encoding.ASCII.GetBytes(pathConfig), pathConfigBuff, pathConfig.Length);
// Call your native method
_ReadTwoBlocks(pathConfigBuff, datablock1Buff, datablock2Buff, TimeOut, ref result);
// If success, copy the datablocks to the StringBuffers
if (result)
{
datablock1.Append(Encoding.ASCII.GetString(datablock1Buff, 0, MAX_STRING).Replace('\0', ' ').Trim());
datablock2.Append(Encoding.ASCII.GetString(datablock2Buff, 0, MAX_STRING).Replace('\0', ' ').Trim());
}
}
答案 1 :(得分:1)
这将是这样的:
[DllImport("IDTechReader.dll")]
private static extern void ReadTwoBlocks(IntPtr pathConfig,
IntPtr datablock1, IntPtr datablock2, int timeout, ref bool ret);
当你像这样使用它时:
string pathConfig = "..\program.ini";
IntPtr ptrPathConfig = IntPtr.Zero;
ptrPathConfig = Marshal.StringToHGlobalAnsi(pathConfig);
IntPtr ptrDatablock1 = IntPtr.Zero;
IntPtr ptrDatablock2 = IntPtr.Zero;
int timeout = 300;
bool ret = false;
ReadTwoBlocks(ptrPathConfig, ptrDatablock1, ptrDatablock2, timeout, ref ret);
string db1 = Marshal.PtrToStringAnsi(ptrDatablock1);
string db2 = Marshal.PtrToStringAnsi(ptrDatablock2);