C++ 如何调用C++;来自C的函数?
我知道这一点 从C++调用C函数:C++ 如何调用C++;来自C的函数?,c++,c,visual-c++,extern-c,C++,C,Visual C++,Extern C,我知道这一点 从C++调用C函数: 如果我的应用程序是C++,我必须调用C中的函数库,那么我就用了 //main.cpp extern "C" void C_library_function(int x, int y);//prototype C_library_function(2,4);// directly using it. 这不会损坏名称C_library_函数,链接器会在其输入*.lib文件中找到相同的名称,问题就解决了 < > >强>从C??< /强> 调用C++函数 但是我在
如果我的应用程序是C++,我必须调用C中的函数库,那么我就用了
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
这不会损坏名称C_library_函数
,链接器会在其输入*.lib文件中找到相同的名称,问题就解决了
< > >强>从C??< /强> 调用C++函数
<>但是我在这里扩展了一个用C编写的大应用程序,我需要使用C++编写的库。C++的名字命名在这里引起了麻烦。链接器正在抱怨未解析的符号。我不能在C项目上使用C++编译器,因为这会破坏很多其他的东西。出路是什么
顺便说一下,我使用MSVC
< >将C++函数导出为Extn“C”(Acc样式符号),或者使用.DEF文件格式来定义C++链接器在创建C++库时未修饰的导出符号,那么,C链接器应该没有问题,阅读它你需要创建一个C API来公开C++代码的功能。基本上,你需要编写C++代码,它被声明为“C”,并且它有一个纯C++ API(不使用类,例如),它封装了C++库。然后使用您创建的纯C包装器库 即使C不是面向对象的,您的C API也可以选择遵循面向对象的样式。例: // *.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);
}
/*.h文件
// ...
#ifdef_uucplusplus
#定义EXTERNC extern“C”
#否则
#定义外部
#恩迪夫
typedef void*mylibrary\u mytype\t;
EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
外部无效mylibrary\u mytype\u destroy(mylibrary\u mytype\u t mytype);
外部无效mylibrary\u mytype\u doit(mylibrary\u mytype\t self,int参数);
#未定义外部
// ...
//*.cpp文件
mylibrary\u mytype\t mylibrary\u mytype\u init(){
返回新的MyType;
}
作废mylibrary\u mytype\u销毁(mylibrary\u mytype\t非类型化\u ptr){
MyType*typed_ptr=静态_cast(非类型化_ptr);
删除键入的\u ptr;
}
void mylibrary\u mytype\u doit(mylibrary\u mytype\t untyped\u self,int参数){
MyType*typed_self=静态_cast(非类型化_self);
键入_self->doIt(参数);
}
< p>假设C++ API是C兼容的(没有类、模板等),可以将它封装在代码>外部“C”{}} /Case>中,就像你在走另一条路时那样。
如果你想公开对象和其他可爱的C++类,你必须编写一个包装器API。
如果你想做这个,你必须在C++中写一个C的包装器。C++是向后兼容的,但是C不是向前兼容的。 我会这样做:
(如果使用MSVC,请忽略GCC编译命令)
假设我有一个C++类,名为“强> AAA < /Stand”,定义在文件<强> AAA.h,AAA.CPP中,并且类<强> AAA < /St>有一个名为“强> Sayi(conchchar * name)< /St>>的方法,我想启用C代码。< /P>
C++类代码<强> AAA <强>纯C++,我不修改它:
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
#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
现在,也在C++中,创建一个C连接器:
在文件aaa_c_connector.h、aaa_c_connector.cpp中定义它。此连接器将定义一个名为AAA_sayHi(cosnt char*name)的C函数,该函数将使用AAA的实例并调用其方法:
aaa\u c\u连接器.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\u c\u连接器.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
#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
现在我有了一个共享库(libaaa_c_connector.so),它实现了c函数AAA_sayHi(const char*name)。现在,我可以创建一个C主文件并将其一起编译:
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
使用C编译命令编译它:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
gcc main.c -L. -laaa_c_connector -o c_aaa
我需要将LD_LIBRARY_PATH设置为包含$PWD,如果我运行可执行文件/c_aaa,我将获得预期的输出:
Hi David
Hi James
编辑:
在某些linux发行版上,最后一个编译命令可能还需要-laaa
和-lstdc++
。感谢@AlaaM。请注意#包括
#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;
}
//////////////
//C++代码//
//////////////
结构A
{
int i;
int j;
A(){i=1;j=2;std::cout您可以在函数声明前面加上extern“C”关键字,例如
外部“C”int Mycppfunction()
{
//代码在这里
返回0
}
有关更多示例,您可以在Google上搜索更多关于“extern”的信息关键字:你需要做的事情不多,但不难,你可以从谷歌得到很多例子。当你控制C++库时:读不可能的复制品……C++库需要重新编译。哦,不,C++ API完全是面向对象的。@爪,见我的文章,制作OOP风格C代码……并创建一个包装库U用C接口来调用这种样式,但是下面是C++实现。然后链接到C接口。你可能想看看包装器的工具,比如SWIG,PyBooP,……做的是等价的东西(但不是C)…谢谢!!得到了。你怎么链接最终的可执行文件?你使用C还是C++?(当我使用C时,链接器找不到C++函数;当我使用C++时,链接器找不到STD::CUT..ZAK),如果您用C++编译器/链接器创建一个静态库,它可以传递性地包括依赖关系(包括C++标准库,它可以由链接器隐式链接)。你应该能够用C++编译器/链接把那个静态库链接到C代码。你能把一个模板从C++导出到C吗?我有一个“混合”的行为,因为我需要我的库被C++和C代码调用。在<代码> *CPP文件< /代码>中,我还需要把函数包成<代码>
以避免链接时出现“未定义的引用”错误。您还可以使用gcc usecpp.c-L-laaa\u c\u connector-Wl,-rpath、-o c\u aaa指定lib链接路径
什么是usecpp.c
?最后一个编译行应该