我正在与一位为C ++开发图书馆的承包商合作。我想知道是否可以在C程序中使用该库。 我使用Gcc作为我的编译器。
答案 0 :(得分:21)
是的,有可能。但是,正如BoBTFish在上面的评论中所说,您(或承包商)必须为C ++库设计一个C接口:
extern "C"
函数。这些函数的接口必须在C中有效,在C ++术语中它们表示它们仅使用POD类型(例如没有引用)并且不抛出异常。您可以将非POD C ++类声明为不完整类型并使用它们的指针,因此通常每个非静态成员函数都由一个函数包装,该函数将指针变为this
作为其第一个参数。#include
在任何需要的地方添加标题)我想你可能认为既然程序是与g ++链接的,那么根据定义它是一个使用C库(恰好包含main
)而不是C的C ++程序使用C ++库的程序。就个人而言,我不打扰争论,重要的一点是你现有的C代码都没有改变。
示例:
lib.h
#ifdef __cplusplus
extern "C"
#endif
int foo();
lib.cpp
#include "lib.h"
#include <vector>
#include <iostream>
int foo() {
try {
std::vector<int> v;
v.push_back(1);
v.push_back(1);
std::cout << "C++ seems to exist\n";
return v.size();
} catch (...) {
return -1;
}
}
的main.c
#include "lib.h"
#include <stdio.h>
int main() {
printf("%d\n", foo());
}
构建
g++ lib.cpp -c -olib.o
gcc main.c -c -omain.o
g++ main.o lib.o -omain
如果您希望在使用gcc
链接和使用g++
之间进行任意区分,则以下内容也适用于第三行:
gcc main.o lib.o -llibstdc++ -omain
但是,我不确定gcc -libstdc++
是否与g++
中的所有可能代码一样有用lib.cpp
。我刚刚测试了这个例子,当然还有很多我没有用过的C ++。
答案 1 :(得分:0)
不,这是不可能的。一件容易被遗漏的事情是异常处理功能。你必须使用c ++编译器编译main。
如果你真的想在c中开发并使用c ++库,你可以开发一个c库,并用g ++编译main。
即使编译成功,链接也会在最后失败。见:
Why can't I link a mixed C/C++ static library that has a C interface using gcc?
并且不仅缺少异常功能。还有很多其他的东西,可以通过使用g ++链接一切来轻松解决。
正如我上面所说,解决方案是从main调用一些函数并用g ++链接它:
#include "my_c_main.h"
int main(int argc, char* argv[])
{
return run_my_c_main( argc, argv );
}
答案 2 :(得分:0)
这个小动态库(g ++)和程序(gcc)完美地编译和链接:
标题 library.h
#ifdef __cplusplus
extern "C" {
#endif
typedef struct TagPerson {} Person;
extern Person* person_create(const char* name);
extern void person_destroy(Person* p);
extern const char* person_name(Person* p);
extern Person* person_exception(Person* p);
#ifdef __cplusplus
}
#endif
C ++ Source library.cc 使用g ++ -shared -fpic library.cc -o libLibrary.so
编译#include <iostream>
#include <string>
#include <stdexcept>
#include "library.h"
namespace Library {
class Person
{
public:
Person(const std::string& name)
: m_name(name)
{
std::cout << m_name << std::endl;
}
const std::string name() const { return m_name; }
void exception() { throw std::runtime_error(""); }
private:
std::string m_name;
};
} // namespace N
extern "C" {
#define PERSON(P) ((Library::Person*)(P))
extern Person* person_create(const char* name) {
try {
return (Person*)(new Library::Person(name));
}
catch(...) {
// Error Procession;
}
return 0;
}
extern void person_destroy(Person* p) {
delete PERSON(p);
}
extern const char* person_name(Person* p) {
return PERSON(p)->name().c_str();
}
extern Person* person_exception(Person* p) {
try {
PERSON(p)->exception();
}
catch(...) {
std::cerr << "Exception" << std::endl;
}
return 0;
}
} // extern "C"
C来源 main.c 使用gcc main.c -lLibrary -o Test
编译#include <stdio.h>
#include "library.h"
int main()
{
Person* p = person_create("Jaco Pastorius");
printf("%s\n", person_name(p));
person_exception(p);
person_destroy(p);
return 0;
}
答案 3 :(得分:-1)
究竟是什么问题?您是否已经使用“错误”语言交付了库,或者您的承包商想要用C ++开发库但是您需要从C链接吗?
在前一种情况下,假设您正确指定了事情,那么您应该将其作为承包商的问题,但如果您没有,或者如果不可能,则需要按照Steve Jessop的建议编写界面。
在后一种情况下,这确实不是问题:承包商需要确保她以可从C调用的形式提供代码,并以安全/安全/稳定方式调用。完成工作的内部代码实际上可以是任何东西,只要她以正确的方式为您包装它。如果您计划自己构建库,则需要它们提供合适的构建脚本,以正确的方式调用编译器。如果您的内部程序员无法应对C ++,我认为存在潜在的维护问题,但这与招聘/就业有关,而不是其工作原理的技术细节。