System.Access违规异常在.Net应用程序中调用C ++ Dll时

时间:2013-10-04 09:56:05

标签: c# c++ unmanaged managed

我正在C#中实现C ++ Dll。

My Wrapper.h文件:

`

    class __declspec(dllexport) TestClass
     {   
      public:
              int value;
              TestClass(int value):value(value)
              {
              }
             ~TestClass()
              {
              }
     }

`

My Wrapper.cpp文件

   #include "stdafx.h"

   #include "WrapperApplication.h"

我的C#代码

 public unsafe class Message:IDisposable
{
   private TestStruct* _testStruct;
   private IntPtr* _oldVTable;
      [DllImport(@"WrapperApplication.dll", EntryPoint = "??0TestClass@WrapperApplication@@QAE@H@Z", CallingConvention = CallingConvention.ThisCall)]
   extern static IntPtr Test(TestStruct* testStruct, int value);

   public Message(int value)
   {
       _testStruct=(TestStruct*)Memory.Alloc(sizeof(TestStruct));

       Test(_testStruct, value);
   }
   #region IDisposable Members

    public void Dispose()
    {

        //throw new NotImplementedException();
    }

    #endregion
}

我的TestStruct.cs文件:

 [StructLayout(LayoutKind.Sequential, Pack = 4)]
  public unsafe struct TestStruct
  {
    public IntPtr* vtable;
    public int value;
  }

我必须在.Net应用程序中的 Vtable 的帮助下调用CPP dll。 我创建了TestStruct.cs文件作为My Cpp类的副本。 并尝试在C#构造函数中调用CPP构造函数。 但是在行测试(_testStruct,value); 会将System.AccessViolation异常抛出为尝试读取或写入内存。这通常表示其他内存已损坏。测试ctor中_teststruct,值的值仍然存在,但仍然会抛出异常。我尝试了很多方法,但未能得到解决方案。请告诉我在实施中我的错误。 所以任何帮助都会得到赞赏。

2 个答案:

答案 0 :(得分:1)

我认为最简单的方法是不直接从C#调用C ++接口DLL。有了这个前提,在你面前会出现两种方式:

  • 为您的DLL提供平面C接口或组件对象模型(COM)接口。这将使其可以从大多数平台和语言调用。
  • 保持DLL原样,但是从C ++ / CLI代码而不是C#代码调用它。毕竟,这就是C ++ / CLI存在的原因:在.Net Framework应用程序和非托管库之间制作这种粘合代码。

答案 1 :(得分:0)

由于您首先调用非托管代码,请确保Dispose()非托管资源。有一种方法可以捕获非托管代码抛出的异常(如果失败的模块是非托管组件)。使用Message()属性装饰HandleProcessCorruptedStateExceptions方法,该属性将捕获非托管代码抛出的任何异常。

  [HandleProcessCorruptedStateExceptions]
   public Message(int value)
   {

    try
      {
         _testStruct=(TestStruct*)Memory.Alloc(sizeof(TestStruct));

         Test(_testStruct, value);
      }
    Catch(AccessViolationException ex)
      {
         //Read the exception here
      }
   }