在.NetcompactFramework(Windows CE)中封送char *

时间:2011-11-10 14:33:55

标签: windows-ce pinvoke

我有来自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)上正常工作

任何想法都得到了回复......谢谢。

2 个答案:

答案 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);