从C调用C ++非成员函数

时间:2014-03-08 17:34:18

标签: c++

我想将模板函数实例的指针传递给C函数作为回调。显然不可能在extern "C"中声明模板。

是否保证C ++对非成员函数使用与C相同的调用约定?在extern "C"中声明一个函数是否有任何其他影响,除了它可以防止不兼容的名称修改?

2 个答案:

答案 0 :(得分:5)

直接为C库导出C ++方法或模板函数是个坏主意。如果我有一个C ++程序,那么我通常将C绑定放入其单独的.cpp + .h文件对中,并使用和extern "C"块包围头文件,并且我在那里只使用C兼容的函数声明。在随附的.cpp文件中,您实现了这些函数,因为它的.cpp文件可以在绑定函数的实际实现中访问C ++特性(模板,类,...),即使它们的签名是C兼容的,使用C友好类型。

在这种情况下,您应该将C绑定函数放入此绑定器.cpp + .h文件中,并且从该函数的实现中,您可以轻松地调用指定模板函数的实例。

简单愚蠢的例子:

<强> CBindings.h:

// This is the header used by both C++ and C
#ifdef __cplusplus
extern "C" {
#endif

    // C compatible function declarations with C-friendly types.
    int int_from_string(const char* s);

#ifdef __cplusplus
}
#endif

<强> CBindings.cpp:

#include "CBindings.h"
#include "WhateverCPPHeader.h"

int int_from_string(const char* s)
{
    // Since the implementation is in a .cpp file here we can do C++ish things.
    return FromString<int>(s);
}

<强> WhateverCPPHeader.h:

// Somewhere in your C++ header files:
template <typename T>
T FromString(const std::string& s);

...
// Template specializations of FromString for several T types
...

<强> Whatever.c:

#include "CBindings.h"
#include <stdio.h>

void my_c_func(void)
{
    int i = int_from_string("5");
    printf("%d\n", i);
}

这适用于所有平台而没有任何问题,C / C ++之间的切割明确地分成了自己的文件。

答案 1 :(得分:3)

没有。它不能保证它使用相同的调用约定。您可以使用调用约定修饰符,如_stdcallcdeclpascal等。因此,您必须确保双方都知道相同的调用约定。

一种方法是检测受损的名称并为C函数定义适当的原型。

考虑改变设计;既然你无法从C中的模板中受益,你可以定义一个简单的C ++函数(定义为extern“C”)来调用模板化函数。