C#P-Invoke:如何将INT fun(BYTE * bStream,UINT16 * nCount,const UINT8 nblk)转换为C#?

时间:2013-05-22 05:19:01

标签: c# c++ winapi pinvoke

使用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);

但它不起作用。 有人可以帮助我吗?谢谢。

1 个答案:

答案 0 :(得分: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并坚持原住民。