AccessViolation,当从 C++/CLI 调用 C++-DLL 时 [英] AccessViolation, when calling C++-DLL from C++/CLI

查看:42
本文介绍了AccessViolation,当从 C++/CLI 调用 C++-DLL 时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为 C++-DLL 编写了一个 C++/CLI 包装器,以便在 C# 程序中使用这个 DLL.

I've written a C++/CLI wrapper for a C++-DLL to use this DLL in a C# programm.

但是,当我调用一个带字符*的函数时,我得到一个 AccessViolation

However, when I call a function, which takes a char* I get a AccessViolation

int Wrapper::Net_methodX(int a, String^ key, long v)
{
    IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
    int val = methodX(a,cKey, v); // AccessViolation here

    Marshal::FreeHGlobal(ptr);
    return val;
}

C++ 函数的签名是

int methodX(int a, char *Key, long v);

编辑 1

仅仅像下面这样固定"也不起作用:

Just to "pin" like the following didn't work either:

int Wrapper::Net_methodX(int a, String^ key, long v)
{
    IntPtr ptr = Marshal::StringToHGlobalAnsi(key);
    char* cKey = static_cast<char*>(ptr.ToPointer());
    pin_ptr<char> pinned = cKey;
    int val = methodX(a,cKey, v);

    Marshal::FreeHGlobal(ptr);
    return val;
}

编辑 1 结束

编辑 2

我也尝试了 PtrToStringChars 以下方式(谢谢马特,还发现了一些文档 这里):

I tried also PtrToStringChars the following way (Thanks Matt, found also some doc here):

int Wrapper::Net_methodX(int a, String^ key, long v)
{
    pin_ptr<const wchar_t> wkey = PtrToStringChars(key);

    size_t convertedChars = 0;
    size_t  sizeInBytes = ((key->Length + 1) * 2);
    errno_t err = 0;
    char * ckey = (char * ) malloc(sizeInBytes);

    err = wcstombs_s(&convertedChars, ckey, sizeInBytes, wkey, sizeInBytes);

    int val = methodX(A_Symbol_Table,ckey, Value);

    return val;
}

仍然出现AccessViolation,可能是methodX()(第三方DLL)出错.

AccessViolation still occurs, maybe it's an error in methodX() (which is a Third-party-DLL).

编辑 2 结束

我在这里阅读了一些相关问题,但还没有找到解决方案.

I have read some related questions here, but did not find a solution yet.

有什么提示吗?谢谢.

推荐答案

Simon,我尝试了您的示例,但没有收到访问冲突.这是我的代码:

Simon, I tried out your example and I do not get an Access Violation. Here's my code:

using namespace System;
using namespace System::Runtime::InteropServices;

ref class Wrapper
{
public:
    static int Net_methodX(int a, String^ key, long v);
};

int methodX(int a, char * pKey, long v)
{
    IntPtr ptr = static_cast<IntPtr>(pKey);
    String ^ pString = Marshal::PtrToStringAnsi(ptr);
    System::Console::WriteLine(pString);
    return a;
}

int Wrapper::Net_methodX(int a, String^ pKey, long v)
{     
    IntPtr ptr = Marshal::StringToHGlobalAnsi(pKey);     
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());     
    int val = methodX(a,cKey, v); // AccessViolation here      
    Marshal::FreeHGlobal(ptr);     
    return val; 
}

void main()
{
    Wrapper wrapper;
    String ^ p = gcnew String("Hello");
    wrapper.Net_methodX(0, p, 0);
}

另外,我有几点意见:

  1. 阅读此处:http://support.microsoft.com/kb/311259 莉>
  2. 您正在使用 pin_ptr 到本机内存.StringToHGlobalAnsi 方法返回本机内存,所以我认为在这里使用 pin_ptr 没有意义.如果您使用的方法可以返回指向托管内存的指针(如 PtrToStringChars),则 pin_ptr 会有意义.除非您正在修改字符串,否则您可能无论如何都希望使用 PtrToStringChars 方法——以避免不必要的分配和复制.
  3. 您会发布导致问题的 methodX 示例版本吗?如果我能重现该问题,我可能会提供更多帮助.

这篇关于AccessViolation,当从 C++/CLI 调用 C++-DLL 时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆