我在 C++ 原生 dll 中有以下函数,我想在 C# 应用程序中使用它。
DWORD __cdecl Foo(
LPCTSTR Input,
TCHAR** Output,
DWORD Options,
ErroneousWord** List = NULL,
LPDWORD Count = 0
);
使用 Pinvoke
[DllImport("dllName", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 Foo(string InputWord, out string Output, UInt32 Options, out object List,out UInt32 Count);
调用代码:
string output;
object dummyError = null;
uint dummyCount = 0;
uint x = 0;
Foo(Text, out output, x | y,out dummyError,out dummyCount);
我得到以下异常
Attempted to read or write protected memory. This is often an indication that other memory is corrupt
附言: ErroneousWord 是结构体,我不需要它的输出,所以我将它编码为对象
最佳答案
该错误很可能意味着您遇到了编码问题。
您没有向我们展示 ErroneousWord
类型是什么,但我假设它是您的 C++ 代码中定义的某种类。我的猜测是它没有被正确编码为 .NET object
。
考虑到它是一个指针(或指向指针的指针),尝试将该参数更改为 IntPtr
type来代表一个指针,而不是。这无关紧要,因为您只是简单地为参数传递 NULL
,使用静态 IntPtr.Zero
field 很容易表示.
您可能还想以完全相同的方式编码 Output
。如果将参数更改为 IntPtr
类型,您将收到一个指向 TCHAR*
的指针,然后您可以将其传递给其他您认为合适的非托管函数(例如,释放它)。
试试下面的代码:
[
DllImport("dllName",
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Cdecl)
]
public static extern UInt32 Foo(
string InputWord,
out IntPtr Output, // change to IntPtr
UInt32 Options,
out IntPtr List, // change to IntPtr
out UInt32 Count);
IntPtr output;
IntPtr dummyError = IntPtr.Zero;
uint dummyCount = 0;
uint x = 0;
Foo(Text, out output, x | y, out dummyError, out dummyCount);
您可能还需要使用 Marshal.AllocHGlobal
method从您的进程中分配 C++ 代码可访问的非托管内存。确保如果你这样做,你也调用相应的 Marshal.FreeHGlobal
method释放内存。
关于c# - Pinvoke 中的一个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6018685/