c# - 为什么它无法在构建为 dll 文件的 c++ 中全局声明一个类?

标签 c# c++ tensorflow dll

我正在开发一个项目,该项目需要一个 dll 文件供另一个用 c# 编写的程序使用。由于我不是很熟悉 C++ 和 C# 从 dll 调用函数的细节...

FIRST - 我以最基本的方式编写了我需要的那些函数

->由A.h、A.cpp组成,用VS2015构建的文件A.exe运行

第二 - 我将上面成功运行的代码修改为可以通过dll文件从c#调用一些函数的格式

->由A.h、A.cpp组成,得到一个从VS2015构建的A.dll

第三 - 我通过一个简单的C#程序测试dll文件的功能

由于代码要用在实时推理上(使用tensorflow的模型),所以我把模型初始化部分写在一个函数里,推理部分写在另一个函数里。我把模型的所有功能都变成了一个类(包括initializeinference)。

我在项目中使用了不止1个模型,模型在初始化后不会被修改。由于它们必须在不同的功能中使用,我决定将每个类(模型)全局化。

//file.h

class UnetInterface
{
public:
    UnetInterface(std::string model_path);

    int predict(cv::Mat srcImage, cv::Mat& dstimage);
private:
    ....
};


//file.cpp

//I put those class declaration outside functions to make them globally

UnetInterface A = UnetInterface(path1);
UnetInterface B = UnetInterface(path2);

UnetInterface::UnetInterface(string model_path)
{
    inp_tensor_name = "input_1:0";
    out_tensor_name = "conv2d_19/Sigmoid:0";
    std::cout << "UnetInerface-> " << model_path << std::endl;

    Status status_load = ReadBinaryProto(Env::Default(), model_path, &graphdef);
    std::cout << ">>>  initial model in InetInterface" << std::endl;
    if (!status_load.ok()) {
        std::cout << "ERROR: Loading model failed..." << std::endl;
        std::cout << model_path << status_load.ToString() << "\n";
    }

    NewSession(SessionOptions(), &session);  //looks like it always stuck in here while initializing
    Status status_create = session->Create(graphdef);
    if (!status_create.ok()) {
        std::cout << "ERROR: Creating graph in session failed.." << status_create.ToString() << std::endl;
    }
    else {
        std::cout << "----------- Successfully created session and load graph -------------" << std::endl;
    }

}

// initialization of those class objects
// this can speed up the speed of inference afterwards
void init()  
{
    A.predict(pic_1);
    B.predict(pic_2);
}

LIB_API void inference(pic)  // the function c# calling for each inference
{
    A.predict(pic_x);
    B.predict(pic_y);
}

上面的声明在我上面提到的第一种方式中工作正常...... https://i.imgur.com/P4xngTj.png

但如果它在 c# 中运行(如下所示的 exe 文件),它总是在初始化时卡住。 https://i.imgur.com/Ts5ZaeK.png

我也试过在.h文件中声明类的方式,在.cpp文件中调用它们,结果和上面的方法一样。

// file.hpp
extern UnetInterface A = UnetInterface(path1);
extern UnetInterface A = UnetInterface(path2);

所以我想出了另外一种方法,初始化后返回一个class的struct。 但是,我不太确定创建类结构的正确方法是什么,这是我到目前为止所做的(有一些错误我写为评论):

//file.h

struct Unets // The struct that stores initialized classes
{
    UnetInterface A;
    UnetInterface B;
};


//file.cpp

Unets init()  // initialization of those class objects
{
    Unets TT;  // error: 'Unets::Unets(void)':attempting to reference a deleted function
               // error: the default constructor of "Unets" cannot be referenced -- it is a deleted function
    TT.A = UnetInterface(path1);
    TT.A.predict(pic1);
    TT.B = UnetInterface(path2);
    TT.B.predict(pic2);
    ...
    ...

    return TT;
}

LIB_API void inference(pic3)  // the function c# calling for each inference
{
    Unets TT2;  // error: the default constructor of "Unets" cannot be referenced -- it is a deleted function
    TT2 = init();
    TT2.predict(pic3);
}

我不知道是否有必要为每次使用函数“推理”重新声明结构“Unets”。如果是,我认为这样写不是一个好主意,所以我被困在这里......

总而言之,我想知道...

<强>1。为什么我声明为 FIRST 方式的全局类在 C# 中运行时失败?

<强>2。最后一种方法是可行的选择吗?如果是/不是,关于返回多个初始化类(模型)的任何其他建议?

(提前感谢您阅读我凌乱的问题描述...

感谢任何建议或帮助 :D )

最佳答案

首先,您需要在此处分离您的问题,因为我看到有两个项目。首先,关于使用全局静态初始化从 Dll 运行代码。其次,关于使用 TensorFlow 推理结构运行代码。

关于第一项,这应该有效。您可以通过使用简单任务(例如,控制台打印输出)而不是 tensorflow 初始化(将它们注释掉)来运行它们来尝试这些。第二项,在您的情况下,可能是第一个 exe 占用了 GPU,因此,第二个 exe 正在等待。

更新

一些代码建议:

//file.cpp
#include <memory>

std::shared_ptr<Unets> init()  // initialization of those class objects
{
    //Unets TT;  // error: 'Unets::Unets(void)':attempting to reference a deleted function
               // error: the default constructor of "Unets" cannot be referenced -- it is a deleted function
    auto TT = std::make_shared<Unets>();

    ...
    ...

    return TT;
}

LIB_API void inference(pic3)  // the function c# calling for each inference
{
    //Unets TT2;  // error: the default constructor of "Unets" cannot be referenced -- it is a deleted function
    auto TT2 = init();
    TT2->A.predict(pic3);
}

关于c# - 为什么它无法在构建为 dll 文件的 c++ 中全局声明一个类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58202051/

相关文章:

c++ - 通过迭代器对 map 的元素求和

c++ - 如何将两组 4 条短裤加载到 XMM 寄存器中?

python - 如何在tensorflow 2.4.1中设置优化器

使用 token 的 C# CSOM Sharepoint 访问

c# - 尝试格式化 DateTime?变量原因 "No overload for method ToString takes 1 argument error"

c++ - Redis pub/sub 序列化数据 struct C 数据

logging - 如何将 TensorFlow 日志重定向到文件?

python - tensorflow ffmpeg contrib 输出

c# - 为什么 0 不能拆箱为整数?

c# - NVelocity 中的 For 循环