努力使用 C# 从本机 DLL 调用方法

Struggling to call the method from native DLL using C#

这是我尝试调用的方法签名。

EXTERN_C
HRESULT
QueryData(
    _Outptr_opt_result_bytebuffer_(*SizeOfData)  PBYTE * Data,
    _Out_opt_                                   UINT32* SizeOfData,
    _In_                                        BOOL    IsDataType
) 

以上方法不是我的代码,它是供应商代码,不幸的是我没有足够的知识来调用这个方法。我所知道的是它应该给我一大堆数据。

这是我到目前为止所做的。

 [DllImport("DataGetter.dll")]
        internal static extern int QueryData(IntPtr data, UIntPtr sizeOfData, bool isDataType);

IntPtr data= new IntPtr();
            UIntPtr sizeOfData= new UIntPtr();
            bool isDataType= true;
            int hresult = QueryData(data, sizeOfData, isDataType);

我的方法没有失败,但 return 数据中没有任何内容。知道如何从 C# 调用这个奇怪的方法吗?

这里有两个问题:首先是将 QueryData 设置的值放入 DatasizeOfData,这会得到指向局部变量的指针。您可以使用 refout 关键字来完成,因此 C++ 中的 UINT32* SizeOfData 变为 ref System.UInt32 SizeOfDataKey difference 之间的是 out 参数不必在函数调用之前初始化。其次是将 C++ 中定义的非托管数组转移到 C# 中。你可以用 Marshall.Copy.

有一件事仍然不清楚,但应该在文档中说明 - 无论何时从 C++ 返回的数组都是动态分配的,并且需要在 C# 中释放或不需要。如果是这样,您将发生内存泄漏,每次调用函数都会增加内存使用量。最简单的测试方法是调用函数 1000000 次并检查内存使用情况。

完整代码:

    [DllImport("DataGetter.dll"]
    internal static extern int QueryData(out IntPtr data, out System.UInt32 sizeOfData, bool isDataType);

    void example()
    {
        IntPtr dataPtr;
        System.UInt32 sizeOfData;
        bool isDataType = false;
        int hresult = QueryData(out dataPtr, out sizeOfData, isDataType);
        var data = new byte[sizeOfData];
        Marshal.Copy(dataPtr, data, 0, (int)sizeOfData);
        // data now contains retreived bytes
    }

旧 POST: 试试。

    [DllImport("DataGetter.dll")]
    internal static extern int QueryData(ref IntPtr data, ref System.UInt32 sizeOfData, bool isDataType);

我不确定 PBYTE 是什么,但我想它是指向 BYTE 的指针。 函数应更改 datasizeOfData 变量。