如何从 C 调用 C++ 函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2744181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to call C++ function from C?
提问by claws
I know this.
我知道这个。
Calling C function from C++:
从 C++ 调用 C 函数:
If my application was in C++ and I had to call functions from a library written in C. Then I would have used
如果我的应用程序是用 C++ 编写的,而我必须从用 C 编写的库中调用函数。那么我会使用
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
This wouldn't mangle the name C_library_function
and linker would find the same name in its input *.lib files and problem is solved.
这不会破坏名称C_library_function
,链接器会在其输入 *.lib 文件中找到相同的名称,问题就解决了。
Calling C++ function from C???
从 C 调用 C++ 函数???
But here I'm extending a large application which is written in C and I need to use a library which is written in C++. Name mangling of C++ is causing trouble here. Linker is complaining about the unresolved symbols. Well I cannot use C++ compiler over my C project because thats breaking lot of other stuff. What is the way out?
但是在这里我要扩展一个用 C 编写的大型应用程序,我需要使用一个用 C++ 编写的库。C++ 的名称修改在这里造成了麻烦。链接器抱怨未解析的符号。好吧,我不能在我的 C 项目上使用 C++ 编译器,因为那会破坏很多其他东西。出路是什么?
By the way I'm using MSVC
顺便说一下,我正在使用 MSVC
回答by Michael Aaron Safyan
You need to create a C API for exposing the functionality of your C++ code. Basically, you will need to write C++ code that is declared extern "C" and that has a pure C API (not using classes, for example) that wraps the C++ library. Then you use the pure C wrapper library that you've created.
您需要创建一个 C API 来公开您的 C++ 代码的功能。基本上,您需要编写声明为 extern "C" 并且具有包装 C++ 库的纯 C API(例如不使用类)的 C++ 代码。然后使用您创建的纯 C 包装库。
Your C API can optionally follow an object-oriented style, even though C is not object-oriented. Ex:
您的 C API 可以选择遵循面向对象的风格,即使 C 不是面向对象的。前任:
// *.h file
// ...
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* mylibrary_mytype_t;
EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);
#undef EXTERNC
// ...
// *.cpp file
mylibrary_mytype_t mylibrary_mytype_init() {
return new MyType;
}
void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
delete typed_ptr;
}
void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
MyType* typed_self = static_cast<MyType*>(untyped_self);
typed_self->doIt(param);
}
回答by SomethingSomething
I would do it in the following way:
我会通过以下方式做到这一点:
(If working with MSVC, ignore the GCC compilation commands)
(如果使用 MSVC,请忽略 GCC 编译命令)
Suppose that I have a C++ class named AAA, defined in files aaa.h, aaa.cpp, and that the class AAAhas a method named sayHi(const char *name), that I want to enable for C code.
假设我有一个名为AAA的 C++ 类,在文件aaa.h、aaa.cpp 中定义,并且类AAA有一个名为sayHi(const char *name) 的方法,我想为 C 代码启用该方法。
The C++ code of class AAA- Pure C++, I don't modify it:
AAA类的C++代码——纯C++,我不修改:
aaa.h
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
Compiling this class as regularly done for C++. This code "does not know" that it is going to be used by C code. Using the command:
像通常为 C++ 所做的那样编译此类。这段代码“不知道”它将被 C 代码使用。使用命令:
g++ -fpic -shared aaa.cpp -o libaaa.so
Now, also in C++, creating a C connector. Defining it in files aaa_c_connector.h, aaa_c_connector.cpp. This connector is going to define a C function, named AAA_sayHi(cosnt char *name), that will use an instance of AAAand will call its method:
现在,同样在 C++ 中,创建一个 C 连接器。在文件aaa_c_connector.h, aaa_c_connector.cpp 中定义它。此连接器将定义一个名为AAA_sayHi(cosnt char *name)的 C 函数,该函数将使用AAA的实例并调用其方法:
aaa_c_connector.h
aaa_c_connector.h
#ifndef AAA_C_CONNECTOR_H
#define AAA_C_CONNECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
void AAA_sayHi(const char *name);
#ifdef __cplusplus
}
#endif
#endif
aaa_c_connector.cpp
aaa_c_connector.cpp
#include <cstdlib>
#include "aaa_c_connector.h"
#include "aaa.h"
#ifdef __cplusplus
extern "C" {
#endif
// Inside this "extern C" block, I can implement functions in C++, which will externally
// appear as C functions (which means that the function IDs will be their names, unlike
// the regular C++ behavior, which allows defining multiple functions with the same name
// (overloading) and hence uses function signature hashing to enforce unique IDs),
static AAA *AAA_instance = NULL;
void lazyAAA() {
if (AAA_instance == NULL) {
AAA_instance = new AAA();
}
}
void AAA_sayHi(const char *name) {
lazyAAA();
AAA_instance->sayHi(name);
}
#ifdef __cplusplus
}
#endif
Compiling it, again, using a regular C++ compilation command:
再次使用常规 C++ 编译命令编译它:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
Now I have a shared library (libaaa_c_connector.so), that implements the C function AAA_sayHi(const char *name). I can now create a C main file and compile it all together:
现在我有一个共享库 (libaaa_c_connector.so),它实现了 C 函数AAA_sayHi(const char *name)。我现在可以创建一个 C 主文件并一起编译它:
main.c
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Compiling it using a C compilation command:
使用 C 编译命令编译它:
gcc main.c -L. -laaa_c_connector -o c_aaa
I will need to set LD_LIBRARY_PATH to contain $PWD, and if I run the executable ./c_aaa, I will get the output I expect:
我需要将 LD_LIBRARY_PATH 设置为包含 $PWD,如果我运行可执行文件./c_aaa,我将得到我期望的输出:
Hi David
Hi James
EDIT:
编辑:
On some linux distributions, -laaa
and -lstdc++
may also be required for the last compilation command. Thanks to @AlaaM. for the attention
在一些Linux发行版,-laaa
并且-lstdc++
可能还需要进行最后的编译命令。感谢@AlaaM。为了引起注意
回答by Marcelo Cantos
Assuming the C++ API is C-compatible (no classes, templates, etc.), you can wrap it in extern "C" { ... }
, just as you did when going the other way.
假设 C++ API 与 C 兼容(没有类、模板等),您可以将它包装在 中extern "C" { ... }
,就像您在其他方式时所做的那样。
If you want to expose objects and other cute C++ stuff, you'll have to write a wrapper API.
如果你想公开对象和其他可爱的 C++ 东西,你必须编写一个包装器 API。
回答by Puppy
You will have to write a wrapper for C in C++ if you want to do this. C++ is backwards compatible, but C is not forwards compatible.
如果你想这样做,你将不得不用 C++ 为 C 编写一个包装器。C++ 向后兼容,但 C 不向前兼容。
回答by Necrolis
export your C++ functions as extern "C" (aka C style symbols), or use the .def file format to define undecorated export symbols for the C++ linker when it creates the C++ library, then the C linker should have no troubles reading it
将您的 C++ 函数导出为 extern "C"(又名 C 样式符号),或者在创建 C++ 库时使用 .def 文件格式为 C++ 链接器定义未修饰的导出符号,那么 C 链接器应该可以轻松读取它
回答by Richard Wicks
#include <iostream>
//////////////
// C++ code //
//////////////
struct A
{
int i;
int j;
A() {i=1; j=2; std::cout << "class A created\n";}
void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;}
~A() {std::cout << "class A destroyed\n";}
};
extern "C" {
// this is the C code interface to the class A
static void *createA (void)
{
// create a handle to the A class
return (void *)(new A);
}
static void dumpA (void *thisPtr)
{
// call A->dump ()
if (thisPtr != NULL) // I'm an anal retentive programmer
{
A *classPtr = static_cast<A *>(thisPtr);
classPtr->dump ();
}
}
static void *deleteA (void *thisPtr)
{
// destroy the A class
if (thisPtr != NULL)
{
delete (static_cast<A *>(thisPtr));
}
}
}
////////////////////////////////////
// this can be compiled as C code //
////////////////////////////////////
int main (int argc, char **argv)
{
void *handle = createA();
dumpA (handle);
deleteA (handle);
return 0;
}
回答by Abubakari UmarblacKrussain Uma
You can prefix the function declaration with extern “C” keyword, e.g.
您可以使用 extern “C” 关键字作为函数声明的前缀,例如
extern “C” int Mycppfunction()
extern “C” int Mycppfunction()
{
{
// Code goes here
// 代码在这里
return 0;
返回0;
}
}
For more examples you can search more on Google about “extern” keyword. You need to do few more things, but it's not difficult you'll get lots of examples from Google.
有关更多示例,您可以在 Google 上搜索更多有关“extern”关键字的信息。您需要做更多的事情,但不难从 Google 获得大量示例。