我正在使用C创建程序。但是,我需要使用许多只有C ++的API。 那么,我是否有可能在C ++中创建共享对象,然后使用C访问其function?
如果无法连接这些代码,我如何从C ++代码获取信息到C代码? 我尝试从C调用C ++函数,但是当我包含时,在链接期间出现错误。 所以当我从C调用C ++函数时,我应该只使用那些与C编译器兼容的代码吗?
C ++头文件cppfile.hpp
#ifndef CPPFILE_H #define CPPFILE_H #ifdef __cplusplus extern "C" { #endif extern int myfunction(const char *filename); #ifdef __cplusplus } #endif #endif
C ++文件cppfile.cpp
#include "cppfile.hpp" #include int myfunction(const char *filename) { String S(filename); return 0; }
C文件cmain.c
#include "cppfile.hpp" int main(int argc, char **argv) { int i = myfunction(argv[1]); printf("%dn", i); return 0; }
编译:
gcc -c cmain.c g++ -fPIC -shared -o cppfile.so cppfile.cpp
你想要更像这样的东西(这里我将使用一个更有意义的例子):
C / C ++标题 – animal.h
#ifndef ANIMAL_H #define ANIMAL_H #ifdef __cplusplus class Animal { public: Animal() : age(0), height(0) {} Animal(int age, float height) : age(age), height(height) {} virtual ~Animal() {} int getAge(); void setAge(int new_age); float getHeight(); void setHeight(float new_height); private: int age; float height; // in metres! }; #endif /* __cplusplus */ #ifdef __cplusplus extern "C" { #endif struct animal; // a nice opaque type struct animal *animal_create(); struct animal *animal_create_init(int age, float height); void animal_destroy(struct animal *a); void animal_setage(struct animal *a, int new_age); void animal_setheight(struct animal *a, float new_height); int animal_getage(struct animal *a); float animal_getheight(struct animal *a); #ifdef __cplusplus } #endif #endif /* ANIMAL_H */
C ++动物实现文件 – animal.cpp
#include "animal.h" #define TO_CPP(a) (reinterpret_cast(a)) #define TO_C(a) (reinterpret_cast(a)) void Animal::setAge(int new_age) { this->age = new_age; } int Animal::getAge() { return this->age; } void Animal::setHeight(float new_height) { this->height = new_height; } float Animal::getHeight() { return this->height; } animal *animal_create() { animal *a = TO_C(new Animal); return a; } animal *animal_create_init(int age, float height) { animal *a = TO_C(new Animal(age, height)); return a; } void animal_destroy(animal *a) { delete TO_CPP(a); } void animal_setage(animal *a, int new_age) { TO_CPP(a)->setAge(new_age); } void animal_setheight(animal *a, float new_height) { TO_CPP(a)->setHeight(new_height); } int animal_getage(animal *a) { TO_CPP(a)->getAge(); } float animal_getheight(animal *a) { TO_CPP(a)->getHeight(); }
C客户端代码 – main.c
#include "animal.h" #include int main() { // 6'0" 25yo (perhaps a human? :P) struct animal *a = animal_create(25, 1.83); animal_setage(a, 26); // birthday printf("Age: %dnHeight: %f", animal_getage(a), animal_getheight(a)); animal_destroy(a); return 0; }
C ++客户端代码 – main.cpp
#include "animal.h" #include int main() { // 6'0" 25yo (perhaps a human? :P) Animal* a = new Animal(25, 1.83); a->setAge(26); // birthday std::cout << "Age: " << a->getAge() << std::endl; std::cout << "Height: " << a->getHeight(); delete a; return 0; }
因此,在编译库时,使用C ++编译器编译animal.cpp
。 然后,您可以使用C代码链接到它,并使用animal_xxx
函数。
注意使用struct animal
和Animal
。 Animal
是一种普通的C ++类型。 它正是它的样子。 另一方面, struct animal
是一种“不透明”类型。 这意味着你的C程序可以看到它,并且可以有一个,但它不知道它里面是什么。 它所知道的是它有一个带struct animal*
的struct animal*
。
在真实的库中,您需要具有内存分配的自定义点。 所以假设这是库libjungle
,你可能至少需要jungle_setmalloc
和jungle_setfree
以及合理的默认值。 然后,您可以在libjungle
的C ++代码中设置全局new
和delete
以使用这些用户定义的函数。
这完全有可能。 以下是快速的方法:1。)你有一个带有C API的header.h,它不包含任何Cplusiness。
#ifndef MIXEDCCPP_H #define MIXEDCCPP_H #ifdef __cplusplus extern "C" { #endif #include // Any C-compatible headers will go here. // C API goes here. C Functions can't contain any CPPiness. void myclass_setName( void *pClassObj, const char *pName, int nameLen ); #ifdef __cplusplus } #endif #ifdef __cplusplus // Stuff that is only compatible with CPP goes here // __cplusplus section won't get processed while compiling C files. #include // CPP headers. class MyClass { // Classes etc. }; #endif // #ifdef __cplusplus #endif // MIXEDCCPP_H
然后在.cpp中,您只需创建一些甚至可以在其中包含CPP的C-API函数:
#include "mixedccpp.h" extern "C" { // C API goes here. C Functions can't contain any CPPiness in their prototypes. void myclass_setName( void *pClassObj, const char *pName, int nameLen ) { // But CPP knowledge can go inside the function - no problem, since this is a CPP file. MyClass *pMyClass = static_cast(pClassObj); pMyClass->setName( pName, nameLen ); } } // #extern "C" // CPP Stuff goes here... or vice-versa.
在您的情况下,您实际上不需要在标头中声明任何CPP代码,因为您正在调用外部库。 但是您需要在CPP文件中创建C兼容的函数,这些函数可以调用CPP库。 对于那些需要从C文件中调用的函数,使用extern“C”,然后使用C-structs代替类,如果需要类,则使用void *指向它们,然后将它们从它们转发回来只要您需要访问它们,C函数就可以运行。 假设它将.cpp文件编译为.cpp并理解extern“C”{},标准的makefile应该能够编译得很好。
您的C代码不能使用C ++头
。 您必须确保将从C调用的C ++ API中的函数声明为extern "C"
(如您所示),并且仅使用C编译器识别的类型(如您所愿)。
如果您的任何代码都在C ++中,您还需要与C ++编译器链接。 如果你准备好花大量精力来获得加载器选项,那么你可以这样做,但是使用C ++编译器要简单得多:
gcc -c cmain.c g++ -fPIC -shared -o cppfile.so cppfile.cpp g++ -o cmain cmain.o cppfile.so
当然,你需要:
此外,如果在没有参数的情况下调用程序,则会得到:
$ ./cmain terminate called throwing an exceptionAbort trap: 6 $ ./cmain x3 0 $
您需要防止滥用,即使在测试程序中也是如此。
以上就是c/c++开发分享我可以在C程序中使用C ++创建的共享库吗?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/573615.html