在调用c ++代码时,获取访问冲突错误是c#

时间:2012-06-01 17:59:34

标签: c# c++ visual-c++ c#-4.0

在c ++中我有以下类

class A
{
  public: 
      int __thiscall check(char *x,char *y,char *z);
  private:
      B *temp;
};

class B
{
  friend class A;
  Public:
    B();
    B(string x,string y,string z);
    ~B();
  private:
    string x;
    string y;
    string z;
};

我在c ++中的dll方法就像这样

__declspec(dllexport) int __thiscall A::check(char *x,char *y,char *z)
{
  temp=new B(x,y,z);
  return 1;
}

B()构造函数的代码如下:

B::B(string x, string y,string z)
{
  .......
}

下面提到的是我的c#dll import

[DllImport("sour.dll", CallingConvention = CallingConvention.ThisCall, ExactSpelling = true, EntryPoint = "check")]
    public static extern void check(IntPtr val,string x,string y,string z);

c ++构建成功完成了任何错误,但是当我使用dll import方法从c#调用此方法时,我正在尝试为“temp”类指针分配内存时出现以下错误。下面提到的是错误。

 Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

任何人都可以帮忙解决这个问题。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我认为导出方法而不是类成员更容易。 请确保DllImport使用正确的调用约定。

__declspec(dllexport) void __cdecl check(int x)

Using PInvoke Interop Assistant results in

public partial class NativeMethods {

    /// Return Type: void
    ///x: int
    [System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="check", CallingConvention=System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static extern  void check(int x) ;

}

您确定您的dll的32/64位版本匹配吗?如果你运行x86 .net版本(32位),你可以激活本机代码和托管代码的调试,你应该能够在C ++方法中设置一个断点,看看会发生什么。

答案 1 :(得分:1)

直接通过PInvoke使用C ++将无法正常工作。首先必须通过堆上的new来实例化C ++类,这是你无法通过managaed代码完成的。

要调用的成员函数需要在DllImport语句中使用thiscall calling约定,因为它是非静态成员方法。这需要隐式地将指针传递给堆栈上的非托管类实例,而这些实例在此处无法实现。

您应该考虑使用托管C++ wrapper class(请参阅链接)直接访问它,或者您创建一个C包装器,您可以将ctor,dtor和实例成员称为接受并返回此指针的直接C方法在必要时。

一个非常hacky的解决方案可能是直接通过Marshal.GlobalAlloc分配内存并通过PInvoke调用此存储位置上的ctor但是因为你现在事先没有需要多少内存,这是一个肮脏的黑客。