Маршалинг char * в .NetcompactFramework (Windows CE) - PullRequest
0 голосов
/ 10 ноября 2011

У меня есть следующая подпись от c ++

IDTECHREADER_EXPORTS void ReadTwoBlocks(char *pathConfig, 
    char *datablock1, char *datablock2, int timeout, bool &ret )

Мне удалось правильно настроить Marshal на 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 (windowsCE)

любые идеи осуществляются ... спасибо.

Ответы [ 2 ]

3 голосов
/ 10 ноября 2011

Маршалер, вероятно, задыхается от 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 голос
/ 10 ноября 2011

Было бы что-то вроде этого:

[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);
...