是否可以在C程序中包含C ++库?

时间:2013-12-02 09:31:00

标签: c++ c gcc

我正在与一位为C ++开发图书馆的承包商合作。我想知道是否可以在C程序中使用该库。 我使用Gcc作为我的编译器。

4 个答案:

答案 0 :(得分:21)

是的,有可能。但是,正如BoBTFish在上面的评论中所说,您(或承包商)必须为C ++库设计一个C接口:

  • 编写一个在C和C ++中编译的头文件,并声明了一些extern "C"函数。这些函数的接口必须在C中有效,在C ++术语中它们表示它们仅使用POD类型(例如没有引用)并且不抛出异常。您可以将非POD C ++类声明为不完整类型并使用它们的指针,因此通常每个非静态成员函数都由一个函数包装,该函数将指针变为this作为其第一个参数。
  • 用C ++实现函数来调用C ++库
  • 将库和包装器编译为C ++
  • 将您的程序编译为C(您可以#include在任何需要的地方添加标题)
  • 将它与g ++链接在一起,以便C ++组件可以链接到libstdc ++。

我想你可能认为既然程序是与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 ++,我认为存在潜在的维护问题,但这与招聘/就业有关,而不是其工作原理的技术细节。