【问题标题】:getting an access violation error is c# while calling the c++ code调用 c++ 代码时出现访问冲突错误是 c#
【发布时间】:2012-06-01 17:59:34
【问题描述】:

在 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 导入

[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 导入方法从 c# 调用此方法时,当我尝试为“temp”类指针分配内存时,出现以下错误。下面提到的是错误。

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

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

【问题讨论】:

  • 没有看到 B 的构造函数的代码,很难说发生了什么。你能把代码也贴出来吗?
  • @Andy----我已经提供了你的要求,你可以看看它。
  • 你的 DllImport 语句是什么样子的?
  • @AloisKraus --- 添加了上面的 dll 导入语句请看一下

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


【解决方案1】:

我认为导出方法而不是类成员更容易。 请确保 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++ 方法中设置断点以查看会发生什么。

【讨论】:

  • 当我这样做时,它给了我一个以前没有给出的错误。
  • @krishna555,我只是假设 __cdecl 但您也必须将调用约定添加到您的代码中。如果您使用 32 位 .net 程序集,您可以激活本机代码的调试。
【解决方案2】:

直接通过 PInvoke 使用 C++ 将不起作用。必须首先通过堆上的 new 实例化 C++ 类,而您无法从托管代码中执行此操作。

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

您应该考虑使用托管C++ wrapper class(参见链接)来直接访问它,或者您制作一个 C 包装器,您可以在其中调用 ctor、dtor 和实例成员作为直接 C 方法,在必要时接受并返回 this 指针.

一个非常 hacky 的解决方案可能是直接通过 Marshal.GlobalAlloc 分配内存并通过 PInvoke 调用此存储位置上的 ctor,但由于您现在不预先知道需要多少内存,这是一个肮脏的 hack。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    相关资源
    最近更新 更多