AccessViolation,从C ++ / CLI调用C ++ - DLL时

时间:2010-12-09 09:21:25

标签: c++-cli access-violation

我为C ++编写了一个C ++ / CLI包装器 - 在C#程序中使用此DLL。

但是,当我调用一个char *函数时,我得到一个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

就像下面的“pin”一样也不起作用:

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(感谢Matt,也发现了一些文档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)中的错误。

编辑2结束

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

任何提示? 谢谢。

3 个答案:

答案 0 :(得分:2)

我知道这是一个老问题,但对于那些偶然发现这个问题寻找答案的人来说,这里有一些更简单的解决方案。

  1. 只需使用sprintf进行如下转换:sprintf(cStr, "%s", clrString);。有关完整示例,请参阅my answer to this question
  2. 按照Matt Smith的建议阅读KB311259。如果您使用的是VS 2008或更高版本,请使用marshal_as<>(KB中的方法#4)。它比该文件中的其他方法简单得多。

答案 1 :(得分:0)

西蒙

我认为以下代码存在问题

pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());

您可能需要阅读此http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0bd049fe-844a-4cb6-b9f6-c8f5107bc957

让我知道它是否对你有帮助。

Sujay

答案 2 :(得分:0)

西蒙 我尝试了你的例子,我没有得到访问冲突。这是我的代码:

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的示例版本吗?如果我可以重现这个问题,我可能会更有帮助。
相关问题