Pinvoke 中的问题
我在 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);
出现以下异常
尝试读或写受保护 记忆。这通常是一个迹象 其他内存已损坏
P.S: ErroneousWord 是结构体,我不需要它的输出,因此我将其封送为对象
I have the following function in C++ native dll, and I want to use it in a C# app.
DWORD __cdecl Foo(
LPCTSTR Input,
TCHAR** Output,
DWORD Options,
ErroneousWord** List = NULL,
LPDWORD Count = 0
);
Using 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);
Calling code:
string output;
object dummyError = null;
uint dummyCount = 0;
uint x = 0;
Foo(Text, out output, x | y,out dummyError,out dummyCount);
I got the following exception
Attempted to read or write protected
memory. This is often an indication
that other memory is corrupt
P.S:
ErroneousWord is struct and I do not need its output, so I marshal it as object
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该错误很可能意味着您遇到了编组问题。
您没有向我们展示
ErroneousWord
类型是什么,但我假设它是您的 C++ 代码中定义的某种类。我的猜测是它没有被正确地编组到 .NET对象
。考虑到它是一个指针(或指向指针的指针),请尝试将该参数更改为
IntPtr
类型 来表示指针。这应该不重要,因为无论如何,您只是为参数传递NULL
,可以使用静态IntPtr.Zero
字段。您可能还想以完全相同的方式封送
Output
。如果将参数更改为IntPtr
类型,您将收到一个指向TCHAR*
的指针,然后您可以将其传递给您认为合适的其他非托管函数(例如,释放它)。尝试以下代码:
您可能还需要使用
Marshal.AllocHGlobal
方法 从进程中分配可供 C++ 代码访问的非托管内存。确保如果这样做,您还调用相应的Marshal.FreeHGlobal
方法 释放内存。That error more than likely means that you have a marshaling problem.
You don't show us what the
ErroneousWord
type is, but I assume it's some kind of class defined in your C++ code. My guess is that it's not being marshaled correctly to a .NETobject
.Considering that it's a pointer (or a pointer to a pointer), try changing that parameter to an
IntPtr
type to represent a pointer, instead. It shouldn't matter, since you're simply passingNULL
for the argument anyway, easily represented using the staticIntPtr.Zero
field.You probably also want to marshal
Output
the exact same way. If you change the parameter to anIntPtr
type, you'll receive a pointer to aTCHAR*
, which you can then pass to the other unmanaged functions however you see fit (e.g., to free it).Try the following code:
You might also need to use the
Marshal.AllocHGlobal
method to allocate unmanaged memory from your process that is accessible to the C++ code. Make sure that if you do so, you also call the correspondingMarshal.FreeHGlobal
method to release the memory.鉴于 Cody 的回答和注释,您必须这样做:
现在要将输出中的字符串值编组到托管内存,您将执行以下操作:
您必须知道 TCHAR 是 Ansi 还是 Unicode,并使用适当的编组。
请记住保留 Output IntPtr,以便可以将其传递给本机 Free 方法。
Given Cody's answer and the comments, you will have to do it this way:
Now to get the string value in Output marshalled over to managed memory you will do:
You must know if TCHAR is Ansi or Unicode and use the appropriate marshal.
Remember to hang onto the Output IntPtr so you can pass that to the native Free method.
感谢 Cody 的回答,但我想制作一个单独的答案,第一个输出是由 Foo 从本机端创建的,我调用 FreeFoo 来释放 Foo 分配的内存。
下面是
使用它的代码:
Thanks Cody for your answer but I want to make a seperate one, first Output is created by Foo from the native side, and I call FreeFoo to free the allocated memory by Foo.
The following is the code
To use it:
无论
ErroneousWord
类型是什么,您都无法将数组编组为单个输出对象。如果有可能作为一个对象编组......Whatever the
ErroneousWord
type is, you can't marshal an array as a single out object. If it is at all possible to marshal as an object...