Visual C#抛出的System.AccessViolationException,在包装的C ++ \ CLI dll中调用Lapack

时间:2013-11-17 14:41:17

标签: c# c++ wrapper lapack

我已经在本机C ++中编写了一些代码,这些代码调用了blas和lapack库的fortran例程(链接为dll)。本机代码运行正常,没有编译器或运行时错误或警告。

现在,我试图将本机C ++包装到.NET框架中使用的dll中,所以我启动了一个Visual C ++项目,编写了一个包装器ref类,将其编译成一个dll并将该dll包含在C#中项目。

在我最终设法将C#项目编译后,我尝试运行它。但是在第一次调用lapack例程时出现运行时错误! (即在Test.cpp中的dpbtrf_( &LOWER, &n, &izero, D.data(), &ione, &info );

错误说:

System.AccessViolationException was unhandled
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
 Source=DotNetTest

我错过了一些编译器选项吗? 或者是否存在本机C ++编译器\运行时没有看到的损坏的内存? 关于如何调试这个的任何提示?

非常感谢!

这是一个微小的复制品,它会产生与原始代码相同的问题(这个问题太广泛了,不能在这里发布):

  1. 原生C ++ Test.h:
  2. 
    
        #ifndef TEST_H_INCLUDED
        #define TEST_H_INCLUDED
    
        #include <vector>
    
        namespace NativeTest
        {
            class Test
            {
                public:
                    Test( int size );
                    ~Test();
    
                    void set( int i, double d );
                    double get( int i ) const;
                    int chol();
                private:
                    std::vector<double> D;
                    int n;
            }; // class Test
        } // namespace NativeTest
    
        #endif // TEST_H_INCLUDED
    
    
    1. 原生C ++ Test.cpp(包含在VC ++项目中)(!用__cdecl编辑):
    2. 
      
          #include "Test.h"
      
          using namespace NativeTest;
      
          const int ione = 1;
          const int izero = 0;
          const char LOWER = 'L';
      
          extern "C"
          {
              // factorization for banded matrix
              void __cdecl dpbtrf_( const char *UPLO, const int *N, const int *KD,
                                    double *AB, const int *LDAB, int *INFO );
          }
      
          Test::Test( int size ) : n( size )
          { D.resize( n ); }
      
          Test::~Test() { }
      
          void Test::set( int i, double d ) { D[ i ] = d; }
      
          double Test::get( int i ) const { return D[ i ]; }
      
          int Test::chol()
          {
              int info = 0;
              dpbtrf_( &LOWER, &n, &izero, D.data(), &ione, &info );
              return info;
          }
      
      
      1. C ++ \ CLI包装器:
      2. 
        
            // TestNet.h
        
            #pragma once
            #include "Test.h"
        
            using namespace System;
        
            namespace DotNetTest {
        
                public ref class TestNet
                {
                    public:
                        TestNet( int size ) { test = new NativeTest::Test( size ); }
                        ~TestNet() { this->!TestNet(); }
                        !TestNet() { delete test; test = NULL; }
        
                        void set( int i, double d ) { test->set( i, d ); }
                        double get( int i ) { return test->get( i ); }
                        int chol() { return test->chol(); }
        
                    protected:
                        NativeTest::Test * test;                
                };
            }
        
        
        1. C#电话:
        2. 
          
              DotNetTest.TestNet t = new DotNetTest.TestNet(2);
              t.set(0, 2);
              t.set(1, 3);
              int info = t.chol();
          
          

1 个答案:

答案 0 :(得分:1)

我修好了,至少对于这里发布的测试代码。我错误地添加了gcc编译的lapack \ blas二进制文件,与我原来的项目(也使用gcc)相同。

今天,我下载了Windows from here的预编译二进制文件,将它们放在我的C#项目的bin文件夹中(连同3个MinGW dll:libgcc_s_dw2-1.dll,libgfortran-3.dll和libquadmath- 0.dll)并确保Visual C ++ \ CLI项目使用相同的库链接(通过将Additional Link Directory设置为C#bin文件夹)。这修复了它,我得到了我想要的结果(没有访问冲突,计算是正确的)。

我还删除了Test.cpp文件的编译选项中的/ clr标志,并关闭该文件的'Use precompiled headers'。