使用void指针作为FFI接口类型

时间:2018-01-25 17:33:11

标签: c++ c ffi

我正在为C ++库编写一个简单的包装器。我有以下类型描述成功的结果或错误:

template<typename T>
struct Result
{
    T value;
    const char* error;

    static Result<T> FromFunction(std::function<T()> function)
    {
        Result<T> result = {};
        try
        {
            result.value = function();
        }
        catch( cv::Exception& e )
        {
            const char* err_msg = e.what();
            auto len = std::strlen(err_msg);
            auto retained_err = new char[len + 1];
            std::strcpy(retained_err, err_msg);
            result.error = retained_err;
        }
        return result;
    }
};

我用它:

extern "C" {
   Result<double> foo() {
      ...
      return result;
   }
}

它适用于GCC (此函数被调用并返回正确的结果),但是,由于模板参数作为函数返回类型,msvc非常沮丧:

error C2526: 'foo': C linkage function cannot return C++ class 'CResult<double>'

我写了以下解决方法,它似乎有效,但我对公共界面中的void*不确定:

void* foo() { {
    return &result;
}

这被认为是一种不好的做法吗?因为我想遵循DRY原则,不要写很多或包装,如ResultDouble,ResultInt等。

2 个答案:

答案 0 :(得分:2)

不确定MSVC有什么问题,但是如果你使用输出参数似乎很高兴(至少在MSVC19-RTW,godbolt上可用的版本)

extern "C" 
{
   void foo( Result<double> * res ) {
      //....
      *res = {};
   }
}

答案 1 :(得分:0)

C没有模板,所以你的编译器是正确的抱怨/错误。

你是一个奇怪的用例,因为技术上你的函数foo有一个完全定义的类型,你可以用C链接导出它(比如在库中)。但是,任何读取该代码段的C编译器都会呕吐,因为C编译器不应该知道模板是什么。