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

发布于 2024-10-07 09:49:38 字数 1696 浏览 3 评论 0原文

我为 C++-DLL 编写了一个 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);

EDIT 1

只是像下面这样“固定”也不起作用:

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以下方式(谢谢马特,还找到了一些文档此处):

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) 。

EDIT 2 END

我在这里阅读了一些相关问题,但尚未找到解决方案。

有什么提示吗? 谢谢。

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

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;
}

The signature of the C++-function is

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

EDIT 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;
}

EDIT 1 END

EDIT 2

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 still occurs, maybe it's an error in methodX() (which is a Third-party-DLL).

EDIT 2 END

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

Any hints?
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只想待在家 2024-10-14 09:49:38

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

  1. 只需使用 sprintf 进行转换,如下所示:sprintf(cStr, "%s", clrString);。有关完整示例,请参阅我对此问题的回答
  2. 按照 Matt Smith 的建议阅读 KB311259。如果您使用的是 VS 2008 或更高版本,请使用 marshal_as(知识库中的方法 #4)。它比该文档中的其他方法简单得多。

I know this is an old question, but for anyone who stumble upon this question looking for an answer, here are some simpler solutions.

  1. Simply use sprintf to do the conversion like this: sprintf(cStr, "%s", clrString);. See my answer to this question for a complete example.
  2. Read KB311259 as suggested by Matt Smith. If you are using VS 2008 or higher, use marshal_as<> (Method #4 in the KB). It's much simpler than the other methods in that document.
鲜肉鲜肉永远不皱 2024-10-14 09:49:38

西蒙,
我尝试了您的示例,但没有遇到访问冲突。这是我的代码:

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

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);
}

Also, I have a few comments:

  1. Read here: http://support.microsoft.com/kb/311259
  2. You are using a pin_ptr to native memory. The StringToHGlobalAnsi method returns native memory, so I don't think using a pin_ptr makes sense here. A pin_ptr would make sense if you were using a method that gives you back a pointer to managed memory (like PtrToStringChars). Unless you are modifying the string, you probably want to go with the PtrToStringChars approach anyways--to avoid unnecessary allocation and copying.
  3. Would you post an example version of methodX that causes the problem? If I can reproduce the issue, I might be able to be more helpful.
坏尐絯 2024-10-14 09:49:38

Simon

我认为以下代码有问题

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

您可能想阅读此http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0bd049fe-844a-4cb6-b​​9f6-c8f5107bc957

请告诉我帮助了你。

苏杰

Simon

I think there is a problem with the following code

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

You might want to read this http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0bd049fe-844a-4cb6-b9f6-c8f5107bc957

Let me know if it helped you.

Sujay

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文