1

我们得到了一个 C# DLL,其中包含加载和操作专有数据格式所需的代码。我们的代码库主要是原生 C++。所以我们可以访问提供的库,我编写了一个 DLL,其中包含

  • 实现必要 API 的本机 C++ 包装类
  • 一个 C++/CLI 桥接类,用于编组输入和输出数据并将调用委托给 C# DLL。

我编写了一个基本的(本机)C++ 控制台应用程序来测试 API 是否符合我的要求。它做了。然后我编写了一个调用 API 的(本机的,Microsoft Visual Studio)单元测试项目。令人惊讶的是,它在构造接口对象时会因一些未说明的异常而崩溃。

一些最小的代码:

互操作API.h:

#pragma once
#pragma unmanaged

#if defined(INTEROP_API_EXPORTS)
#define INTEROP_API __declspec(dllexport)
#else
#define INTEROP_API __declspec(dllimport)
#endif

#include <string>

class InteropBridgeArchive;

struct InteropRecord
{
    std::string Name;
    int Id;
    std::string Data;
};

class INTEROP_API InteropAPI
{
public:
    InteropAPI();
    ~InteropAPI();

    InteropRecord GetRecord(int id) const;

private:
    InteropBridgeArchive * impl_;
};

互操作API.cpp:

#pragma managed
#include "InteropBridge.h"
#pragma unmanaged
#include "InteropAPI.h"

InteropAPI::InteropAPI()
: impl_(new InteropBridge())
{   
}

InteropAPI::~InteropAPI()
{
    delete impl_;
}

InteropRecord InteropAPI::GetRecord(const int id) const
{
    return impl_->GetRecord(id);
}

互操作桥.h

#pragma once
#pragma unmanaged
#include "InteropAPI.h"

#pragma managed

#include <vcclr.h>

class InteropBridge
{
public:
    InteropArchive();
    InteropRecord GetRecord(System::Int32 id) const;

private:
    gcroot<InteropCSharpDll::Archive^> archive_;
};

互操作桥.cpp:

#pragma unmanaged
#include <string>
#pragma managed
#include "InteropBridge.h"
#include <msclr/marshal_cppstd.h>

InteropBridge::InteropBridge()
{
    archive_ = gcnew InteropCSharpDll::Archive;
}

InteropRecord InteropBridge::GetRecord(const System::Int32 id) const
{
    auto return_value = archive_->GetRecord(id);
    InteropRecord record;
    record.Name = msclr::interop::marshal_as<std::string>(return_value.Name);
    record.Id = return_value.Id;
    record.Data = msclr::interop::marshal_as<std::string>(return_value.Data);
    return record;
}

测试 C# DLL 有这个:

using System.Linq;

namespace InteropCSharpDll
{
    public struct Record
    {
        public string Name;
        public int Id;
        public string Data;
    }

    public class Archive
    {
        public Record GetRecord(int id)
        {
            return _records.First(r => r.Id == id);
        }

        private readonly Record[] _records = 
        {
            new Record {Name = "Foo", Id = 0, Data = "Foo.Data"},
            new Record {Name = "Bar", Id = 2, Data = "Bar.Data"},
            new Record {Name = "Egg", Id = 7, Data = "Egg.Data"},
        };
    }
}

显然,如果这种混合结构不能作为本机代码进行单元测试,我们就无法测试任何接触它的东西,因此了解它崩溃的原因非常重要。此代码作为本机 C++ 项目运行良好:

#include <cstdio>
#include <iostream>
#include "../InteropCppCliBridgeDll/InteropAPI.h"

#pragma comment(lib, "../x64/Debug/InteropCppCliBridgeDll.lib")

int main(int , char ** )
{
    const InteropAPI archive;
    const auto record = archive.GetRecord(0);
    std::cout << "Name: " << record.Name << "\n";
    std::cout << "Id: " << record.Id<< "\n";
    std::cout << "Data: " << record.Data<< "\n\n";
}

而在本机单元测试项目中,崩溃发生在行内或行周围

archive_ = gcnew InteropCSharpDll::Archive;
4

0 回答 0