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

时间:2021-11-14 05:52:42

I'm working with a contractor who develops a library for us in C++. I would like to know if it is possible to use that library in a C program. I am using Gcc as my compiler.

我正在和一个为我们开发c++图书馆的承包商合作。我想知道是否有可能在C程序中使用那个库。我使用Gcc作为我的编译器。

4 个解决方案

#1


0  

No, it is not possible. One thing that is certanly going to miss are exception handling functions. You have to compile the main using c++ compiler.

不,这是不可能的。肯定会漏掉的一件事是异常处理函数。您必须使用c++编译器编译主程序。

If you really want to develop in c, and use a c++ library, you can develop a c library, and compile main with g++.

如果您真的想在c语言中进行开发,并使用c++库,您可以开发一个c语言库,并使用g++编译main。


Even if compiling succeeds, linking will fail at the end. See : Why can't I link a mixed C/C++ static library that has a C interface using gcc?
And it is not only exception functionality missing. There are lots of other things, which can be easily solved by using g++ to link everything.

即使编译成功,链接最终也会失败。看:为什么我不能链接一个混合的C/ c++静态库,它使用gcc提供一个C接口?而且,它不仅缺少异常功能。还有很多其他的东西,可以通过使用g++链接所有的东西来轻松解决。

As I said above, the solution is to call some function from main and link it with g++ :

如上所述,解决方案是调用main函数中的某个函数,并将其与g++联系起来:

#include "my_c_main.h"

int main(int argc, char* argv[])
{
  return run_my_c_main( argc, argv );
}

#2


21  

Yes, it is possible. However, as BoBTFish says in a comment above, you (or the contractor) must design a C interface for the C++ library:

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

  • write a header file that compiles in both C and C++, and that declares some extern "C" functions. The interfaces of these functions must be valid in C, which in C++ terms means they use only POD types (for example no references) and don't throw exceptions. You can declare non-POD C++ classes as incomplete types and use pointers to them, so commonly each non-static member function is wrapped by a function that takes the pointer that will become this as its first parameter.
  • 编写一个头文件,该头文件在C和c++中编译,并声明一些外部“C”函数。这些函数的接口在C中必须是有效的,在c++中,这意味着它们只使用POD类型(例如没有引用),并且不抛出异常。您可以将非pod c++类声明为不完整的类型,并使用指向它们的指针,因此通常每个非静态成员函数都被一个函数包装,该函数将会成为它的第一个参数。
  • implement the functions in C++ to call the C++ library
  • 在c++中实现函数来调用c++库
  • compile the library and the wrapper as C++
  • 编译库和包装器为c++。
  • compile your program as C (you can #include the header wherever needed)
  • 把你的程序编译成C(你可以在任何需要的地方包括标题)
  • link it all together with g++ so that the C++ components can link against libstdc++.
  • 将它与g++链接在一起,以便c++组件可以链接到libstdc++。

I suppose you might argue that since the program is linked with g++, it's by definition a C++ program that uses a C library (that happens to contain main) rather than a C program that uses a C++ library. Personally I wouldn't bother arguing that, the important point is that none of your existing C code changes.

我想你可能会说,由于这个程序是与g++链接的,所以根据定义,它是使用C库(碰巧包含main)的c++程序,而不是使用c++库的C程序。就我个人而言,我不想争论这个问题,重要的一点是您现有的C代码没有任何变化。

Example:

例子:

lib.h

lib.h

#ifdef __cplusplus
extern "C"
#endif
int foo();

lib.cpp

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

c

#include "lib.h"
#include <stdio.h>

int main() {
    printf("%d\n", foo());
}

build

构建

g++ lib.cpp -c -olib.o
gcc main.c -c -omain.o
g++ main.o lib.o -omain

The following also works instead of the third line, if you do want to make an arbitrary distinction between using gcc to link and using g++:

如果您想要在使用gcc和使用g++之间进行任意的区分,那么下面的方法也可以替代第三行。

gcc main.o lib.o -llibstdc++ -omain

However, I am not certain that gcc -libstdc++ will work as well as g++ for all possible code that could be in lib.cpp. I just tested it for this example, and of course there's a lot of C++ that I haven't used.

但是,我不确定gcc -libstdc++对于所有可能在lib.cpp中使用的代码来说,gcc -libstdc++和g++的性能是一样的。我只是对这个例子进行了测试,当然还有很多c++我没有用到。

#3


0  

This little dynamic library (g++) and program (gcc) compiles and links perfectly:

这个小的动态库(g++)和程序(gcc)完美地编译和链接:

Header library.h

头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 compiled with g++ -shared -fpic library.cc -o libLibrary.so

c++源代码库。使用g++共享-fpic库编译。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 Source main.c compiled with gcc main.c -lLibrary -o Test

C的主要来源。c使用gcc main编译。c -lLibrary - o测试

#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;
}

#4


-1  

What exactly is the issue? Do you already have a delivered library in the "wrong" language or is it that your contractor wants to develop the library in C++ but you need it to link from C?

问题到底是什么?您是否已经有一个“错误”语言的交付库,还是您的承包商希望用c++开发库,但您需要它从C链接?

In the former case, assuming you specified things correctly you should make it your contractor's problem but if you didn't or if that's not possible you'll need to write an interface as Steve Jessop suggests above.

在前一种情况下,假设你指定的东西是正确的你应该把它作为你的承包人的问题,但是如果你没有或者如果不可能,你需要像Steve Jessop上面建议的那样写一个接口。

In the latter case, it's really not an issue: the contractor will need to ensure that she provides the code in a form that is callable from C and safe/secure/stable to call in that manner. The internal code that does the work can really be anything at all providing she wraps it up for you in the correct manner. If you're planning on building the library yourself, you will need them to provide suitable build scripts that invoke the compiler in the right manner. I guess there's a potential maintenance issue if your in-house programmers can't cope with C++ but that's an issue to do with recruitment/employment not the technical details of how it works.

在后一种情况下,这真的不是问题:承包商需要确保她以一种可从C调用的形式提供代码,并以这种方式调用安全/安全/稳定。做这项工作的内部代码可以是任何东西,只要她以正确的方式为您包装它。如果您正在计划自己构建库,您将需要它们以正确的方式调用编译器,从而提供合适的构建脚本。我猜,如果你的内部程序员无法处理c++,那么可能会有一个维护问题,但这是一个与招聘/雇佣有关的问题,而不是它如何工作的技术细节。

#1


0  

No, it is not possible. One thing that is certanly going to miss are exception handling functions. You have to compile the main using c++ compiler.

不,这是不可能的。肯定会漏掉的一件事是异常处理函数。您必须使用c++编译器编译主程序。

If you really want to develop in c, and use a c++ library, you can develop a c library, and compile main with g++.

如果您真的想在c语言中进行开发,并使用c++库,您可以开发一个c语言库,并使用g++编译main。


Even if compiling succeeds, linking will fail at the end. See : Why can't I link a mixed C/C++ static library that has a C interface using gcc?
And it is not only exception functionality missing. There are lots of other things, which can be easily solved by using g++ to link everything.

即使编译成功,链接最终也会失败。看:为什么我不能链接一个混合的C/ c++静态库,它使用gcc提供一个C接口?而且,它不仅缺少异常功能。还有很多其他的东西,可以通过使用g++链接所有的东西来轻松解决。

As I said above, the solution is to call some function from main and link it with g++ :

如上所述,解决方案是调用main函数中的某个函数,并将其与g++联系起来:

#include "my_c_main.h"

int main(int argc, char* argv[])
{
  return run_my_c_main( argc, argv );
}

#2


21  

Yes, it is possible. However, as BoBTFish says in a comment above, you (or the contractor) must design a C interface for the C++ library:

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

  • write a header file that compiles in both C and C++, and that declares some extern "C" functions. The interfaces of these functions must be valid in C, which in C++ terms means they use only POD types (for example no references) and don't throw exceptions. You can declare non-POD C++ classes as incomplete types and use pointers to them, so commonly each non-static member function is wrapped by a function that takes the pointer that will become this as its first parameter.
  • 编写一个头文件,该头文件在C和c++中编译,并声明一些外部“C”函数。这些函数的接口在C中必须是有效的,在c++中,这意味着它们只使用POD类型(例如没有引用),并且不抛出异常。您可以将非pod c++类声明为不完整的类型,并使用指向它们的指针,因此通常每个非静态成员函数都被一个函数包装,该函数将会成为它的第一个参数。
  • implement the functions in C++ to call the C++ library
  • 在c++中实现函数来调用c++库
  • compile the library and the wrapper as C++
  • 编译库和包装器为c++。
  • compile your program as C (you can #include the header wherever needed)
  • 把你的程序编译成C(你可以在任何需要的地方包括标题)
  • link it all together with g++ so that the C++ components can link against libstdc++.
  • 将它与g++链接在一起,以便c++组件可以链接到libstdc++。

I suppose you might argue that since the program is linked with g++, it's by definition a C++ program that uses a C library (that happens to contain main) rather than a C program that uses a C++ library. Personally I wouldn't bother arguing that, the important point is that none of your existing C code changes.

我想你可能会说,由于这个程序是与g++链接的,所以根据定义,它是使用C库(碰巧包含main)的c++程序,而不是使用c++库的C程序。就我个人而言,我不想争论这个问题,重要的一点是您现有的C代码没有任何变化。

Example:

例子:

lib.h

lib.h

#ifdef __cplusplus
extern "C"
#endif
int foo();

lib.cpp

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

c

#include "lib.h"
#include <stdio.h>

int main() {
    printf("%d\n", foo());
}

build

构建

g++ lib.cpp -c -olib.o
gcc main.c -c -omain.o
g++ main.o lib.o -omain

The following also works instead of the third line, if you do want to make an arbitrary distinction between using gcc to link and using g++:

如果您想要在使用gcc和使用g++之间进行任意的区分,那么下面的方法也可以替代第三行。

gcc main.o lib.o -llibstdc++ -omain

However, I am not certain that gcc -libstdc++ will work as well as g++ for all possible code that could be in lib.cpp. I just tested it for this example, and of course there's a lot of C++ that I haven't used.

但是,我不确定gcc -libstdc++对于所有可能在lib.cpp中使用的代码来说,gcc -libstdc++和g++的性能是一样的。我只是对这个例子进行了测试,当然还有很多c++我没有用到。

#3


0  

This little dynamic library (g++) and program (gcc) compiles and links perfectly:

这个小的动态库(g++)和程序(gcc)完美地编译和链接:

Header library.h

头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 compiled with g++ -shared -fpic library.cc -o libLibrary.so

c++源代码库。使用g++共享-fpic库编译。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 Source main.c compiled with gcc main.c -lLibrary -o Test

C的主要来源。c使用gcc main编译。c -lLibrary - o测试

#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;
}

#4


-1  

What exactly is the issue? Do you already have a delivered library in the "wrong" language or is it that your contractor wants to develop the library in C++ but you need it to link from C?

问题到底是什么?您是否已经有一个“错误”语言的交付库,还是您的承包商希望用c++开发库,但您需要它从C链接?

In the former case, assuming you specified things correctly you should make it your contractor's problem but if you didn't or if that's not possible you'll need to write an interface as Steve Jessop suggests above.

在前一种情况下,假设你指定的东西是正确的你应该把它作为你的承包人的问题,但是如果你没有或者如果不可能,你需要像Steve Jessop上面建议的那样写一个接口。

In the latter case, it's really not an issue: the contractor will need to ensure that she provides the code in a form that is callable from C and safe/secure/stable to call in that manner. The internal code that does the work can really be anything at all providing she wraps it up for you in the correct manner. If you're planning on building the library yourself, you will need them to provide suitable build scripts that invoke the compiler in the right manner. I guess there's a potential maintenance issue if your in-house programmers can't cope with C++ but that's an issue to do with recruitment/employment not the technical details of how it works.

在后一种情况下,这真的不是问题:承包商需要确保她以一种可从C调用的形式提供代码,并以这种方式调用安全/安全/稳定。做这项工作的内部代码可以是任何东西,只要她以正确的方式为您包装它。如果您正在计划自己构建库,您将需要它们以正确的方式调用编译器,从而提供合适的构建脚本。我猜,如果你的内部程序员无法处理c++,那么可能会有一个维护问题,但这是一个与招聘/雇佣有关的问题,而不是它如何工作的技术细节。