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函数:

如果我的应用程序是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
?最后一个编译行应该