-2

有了 C/C++ DLL SDK 的乐趣,像这样:

    INT CmdGetAllLog( BYTE *bStream, UINT16 *nCount, const UINT8 nblk )

但在项目中使用 c#,我这样做:

    [DllImport("C:\\PrBioApi.dll", EntryPoint = "CmdGetAllLog")]
    private static extern bool CmdGetAllLog(IntPtr bStream, ref UInt16 nCount, byte nblk);

我将它用于:

                    int nMallocSize = Marshal.SizeOf(new LOG_RECORD()) * stuSystem.wLogCnt + 4096;
                    byte[] pRecord = new byte[nMallocSize];
                    IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(nMallocSize));
                    Marshal.Copy(pRecord, 0, p, pRecord.Length);

                    bGetSucc = CmdGetAllLog(p, ref nGet, nBlk++);

                    Marshal.FreeHGlobal(p);

但它没有用。有人可以帮助我吗?谢谢。

4

1 回答 1

0

您在托管数组和非托管指针之间复制的代码位于错误的位置。它需要在调用非托管函数之后。

但是您也可以让 p/invoke marshaller 为您完成工作:

[DllImport(@"C:\PrBioApi.dll")]
private static extern bool CmdGetAllLog(
    byte[] bStream, 
    ref ushort nCount, 
    byte nblk
);

int nMallocSize = ...;
byte[] pRecord = new byte[nMallocSize];
bool bGetSucc = CmdGetAllLog(pRecord, ref nGet, nBlk++);

因为字节数组是 blittable 的,所以编组器将在调用期间固定您的数组并将其交给本机代码。

我假设其他两个参数正确传递。由于您没有指定界面的更多详细信息,因此它们很可能是错误的。我猜这nGet是用来告诉函数缓冲区有多大,并返回函数复制了多少。我看不到您nGet在问题中指定的位置。我相信你说得对。

其他一些评论:

  1. 您可能需要在DllImport属性中指定调用约定。cdecl也许是本机代码?
  2. 返回值INT在本机代码中,但您已将其映射到bool. 如果协议是非零返回意味着成功,那可能很好。但如果返回值表明的不止于此,那么您显然需要使用int. 就个人而言,我倾向于使用int并忠于本地人。
于 2013-05-22T05:26:43.840 回答