我在C ++ native dll中有以下功能,我想在C#app中使用它。
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);
我收到了以下异常
尝试读取或写入受保护的 记忆。这通常是一个迹象 其他内存已损坏
P.S: ErroneousWord是struct,我不需要它的输出,所以我将它作为对象
编组答案 0 :(得分:3)
这个错误很可能意味着你有一个编组问题。
您没有向我们展示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来释放内存。
答案 1 :(得分:2)
考虑到Cody的回答和评论,你必须这样做:
[DllImport("dllName", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
extern static UInt32 Foo(string InputWord, out IntPtr Output, UInt32 Options, out IntPtr List, out UInt32 Count);
现在要将Output中的字符串值编组到托管内存中,您将执行以下操作:
string outputValue = Marshal.PtrToStringAnsi(Output);
您必须知道TCHAR是Ansi还是Unicode并使用适当的编组。
请记住挂起输出IntPtr,以便将其传递给本机Free方法。
答案 2 :(得分:2)
感谢Cody的答案,但是我想要单独制作,首先输出是由Foo从本机创建的,我调用FreeFoo来释放Foo分配的内存。 以下是代码
[DllImport("dllname", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 Correct(string InputWord, out IntPtr Output, UInt32 Options, out object List,out UInt32 Count);
[DllImport("dllname", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern void FreeFoo(IntPtr Output);
}
使用它:
public string FooWrapper(string Text)
{
IntPtr output;
object dummyError = null;
uint dummyCount = 0;
uint x = 0;
Foo(Text, out output, x,out dummyError,out dummyCount);
string str = Marshal.PtrToStringUni(output);
FreeFoo(output);
return str;
}
答案 3 :(得分:1)
无论ErroneousWord
类型是什么,您都无法将数组编组为单个输出对象。如果有可能作为一个对象编组...