C++ cli 调用C+时的访问冲突+-来自C++/CLI

C++ cli 调用C+时的访问冲突+-来自C++/CLI,c++-cli,access-violation,C++ Cli,Access Violation,我已经为一个C++-DLL编写了一个C++/CLI包装器,以便在C#程序中使用这个DLL 然而,当我调用一个函数时,它接受一个字符*我得到一个accessinvalition int Wrapper::Net_methodX(int a, String^ key, long v) { IntPtr ptr = Marshal::StringToHGlobalAnsi(key); pin_ptr<char> cKey = static_cast<char*>

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

然而,当我调用一个函数时,它接受一个字符*我得到一个accessinvalition

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;
}
编辑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;
}
int包装器::Net_methodX(int a,字符串^key,长v)
{
IntPtr ptr=Marshal::StringToHGlobalAnsi(键);
char*cKey=static_cast(ptr.ToPointer());
pin_ptr pinted=cKey;
int val=方法x(a,cKey,v);
元帅:自由全球(ptr);
返回val;
}
编辑1结尾

编辑2

我也用以下方法尝试了PtrToStringChars(谢谢Matt,还找到了一些doc):

int包装器::Net_methodX(int a,字符串^key,长v)
{
pin_ptr wkey=PtrToStringChars(键);
大小\u t convertedChars=0;
大小\u t大小字节=((键->长度+1)*2);
errno\u t err=0;
char*ckey=(char*)malloc(sizeInBytes);
err=wcstombs_s(和转换字符、ckey、大小字节、wkey、大小字节);
int val=methodX(符号表,ckey,值);
返回val;
}
AccessViolation仍然发生,可能是methodX()中的错误(这是第三方DLL)

编辑2结尾

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

有什么提示吗? 谢谢。西蒙

我认为下面的代码有问题

pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
pin_ptr cKey=static_cast(ptr.ToPointer());
你可能想看看这个

如果对你有帮助,请告诉我

苏杰

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

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);
}
使用名称空间系统;
使用名称空间System::Runtime::InteropServices;
ref类包装器
{
公众:
静态int Net_methodX(int a,字符串^key,长v);
};
int methodX(int a,char*pKey,long v)
{
IntPtr ptr=静态铸件(pKey);
字符串^pString=Marshal::PtrToStringAnsi(ptr);
系统::控制台::写线(pString);
返回a;
}
int包装器::Net_methodX(int a,字符串^pKey,长v)
{     
IntPtr ptr=Marshal::StringToHGlobalAnsi(pKey);
pin_ptr cKey=静态(ptr.ToPointer());
int val=methodX(a,cKey,v);//此处存在访问冲突
元帅:自由全球(ptr);
返回val;
}
void main()
{
包装纸;
String ^p=gcnewstring(“Hello”);
wrapper.Net_methodX(0,p,0);
}
此外,我有几点意见:

  • 请看这里:
  • 您正在对本机内存使用pin_ptr。StringToHGlobalAnsi方法返回本机内存,因此我认为在这里使用pin_ptr没有意义。如果您使用的方法返回一个指向托管内存的指针(如PtrToStringChars),那么pin_ptr是有意义的。除非您正在修改字符串,否则您可能希望使用PtrToStringChars方法——以避免不必要的分配和复制
  • 您是否会发布导致问题的methodX的示例版本?如果我能重现这个问题,我可能会更有帮助

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

  • 只需使用
    sprintf
    进行如下转换:
    sprintf(cStr,“%s”,clrString)。有关完整示例,请参见
  • 按照马特·史密斯的建议阅读。如果您使用的是VS 2008或更高版本,请使用
    marshal_as
    (KB中的方法4)。它比文档中的其他方法简单得多

  • 正如链接中所建议的,我试图“锁定”cKey以避免GC,并向C++函数传递了一个char*。但是访问冲突仍然发生。感谢您在2的澄清。我尝试使用PtrToStringChars(请参阅我的原始帖子中的编辑2),但AccessViolation仍然发生。不幸的是methodX()来自第三方DLL,因此没有源代码,只有糟糕的文档。我刚刚得到一个跟踪,该方法是用a、key和v的值输入的。为了消除methodX是问题所在的可能性,您是否尝试过传入一个本机分配的char*(实际上,看起来您的edit2尝试了这一点)?如果你得到一个方法已经被输入的跟踪,那么我怀疑methodX是罪魁祸首(或者你正在传递它意想不到的东西)。是的,我假设问题也在methodX中。我只是想确保包装中没有错误。谢谢你的帮助。我刚才也遇到过同样的问题
    Marshall_as
    最终为我出色地完成了工作,而我以前在
    Marshall::StringToHGlobalAnsi
    方面遇到了麻烦。
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());
    
    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);
    }