kic*_*r86 29 c c++ compilation shared-libraries
我正在使用C创建程序.但是,我需要使用许多只有C++的API.那么,我是否有可能在C++中创建共享对象,然后使用C访问其功能?
如果无法连接这些代码,我如何从C++代码获取信息到C代码?我尝试从C调用C++函数,但是当我包含时,我在链接期间遇到错误<string>
.所以当我从C调用C++函数时,我应该只使用那些与C编译器兼容的代码吗?
#ifndef CPPFILE_H
#define CPPFILE_H
#ifdef __cplusplus
extern "C" {
#endif
extern int myfunction(const char *filename);
#ifdef __cplusplus
}
#endif
#endif
Run Code Online (Sandbox Code Playgroud)
#include "cppfile.hpp"
#include <string>
int myfunction(const char *filename) {
String S(filename);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
#include "cppfile.hpp"
int main(int argc, char **argv)
{
int i = myfunction(argv[1]);
printf("%d\n", i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
gcc -c cmain.c
g++ -fPIC -shared -o cppfile.so cppfile.cpp
Run Code Online (Sandbox Code Playgroud)
Mil*_*out 28
你想要更像这样的东西(在这里我将使用一个更有意义的例子):
#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 */
Run Code Online (Sandbox Code Playgroud)
#include "animal.h"
#define TO_CPP(a) (reinterpret_cast<Animal*>(a))
#define TO_C(a) (reinterpret_cast<animal*>(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();
}
Run Code Online (Sandbox Code Playgroud)
#include "animal.h"
#include <stdio.h>
int main()
{
// 6'0" 25yo (perhaps a human? :P)
struct animal *a = animal_create(25, 1.83);
animal_setage(a, 26); // birthday
printf("Age: %d\nHeight: %f", animal_getage(a), animal_getheight(a));
animal_destroy(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
#include "animal.h"
#include <iostream>
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;
}
Run Code Online (Sandbox Code Playgroud)
因此,在编译库时,animal.cpp
使用C++编译器进行编译.然后,您可以使用C代码链接到它,并使用这些animal_xxx
功能.
注意使用struct animal
和Animal
.Animal
是一个普通的C++类型.它正是它的样子.struct animal
另一方面,是一种"不透明"类型.这意味着你的C程序可以看到它,并且可以有一个,但它不知道里面是什么.它只知道它有一个功能需要一个struct animal*
.
在真正的库中,您需要具有内存分配的自定义点.因此,假设这是库libjungle
,您可能至少需要jungle_setmalloc
并且jungle_setfree
具有合理的默认值.然后,您可以设置global new
和delete
in libjungle
的C++代码以使用这些用户定义的函数.
c.f*_*lou 10
这是完全可能的.以下是如何快速地:1.)您有一个带有C API的header.h,它不包含任何Cplusiness.
#ifndef MIXEDCCPP_H
#define MIXEDCCPP_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> // 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 <vector> // CPP headers.
class MyClass {
// Classes etc.
};
#endif // #ifdef __cplusplus
#endif // MIXEDCCPP_H
Run Code Online (Sandbox Code Playgroud)
然后在.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<MyClass *>(pClassObj);
pMyClass->setName( pName, nameLen );
}
} // #extern "C"
// CPP Stuff goes here... or vice-versa.
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您实际上不需要在标头中声明任何CPP代码,因为您正在调用外部库.但是您需要在CPP文件中创建C兼容的函数,这些函数可以调用CPP库.对于那些需要从C文件中调用的函数,使用extern"C",然后使用C-structs而不是类,如果需要类,则使用void*指向它们,然后将它们从它们转发回来只要您需要访问它们,C函数就可以运行.假设它将.cpp文件编译为.cpp并理解extern"C"{},标准的makefile应该能够编译得很好.