如何将C++静态库链接到C程序?

6

I have the following c++ program:

Client.h

#ifndef Client_Client_h
#define Client_Client_h

#include "Client.h"

class Client {

public:
    void f1();
    void f2();
};

#endif

Client.cpp

#include <iostream>
#include <stdlib.h>
using namespace std;

#include "Client.h"

void Client::f1(){
    cout << "Client.f1()" << endl;
}

void Client::f2() {
    cout << "Client.f2()" << endl;
}

在XCode 4.3中编译以上内容,会生成一个名为静态库文件:的文件。
libClient.a

另外,我有一个 main.c 文件。

#include <stdio.h>
//
//using namespace std;

int main(){
        // how do I do something like: Client c; c.f1(); c.f2(); 
        // and actually get output ? 
        printf("hello\n");
        return 0;
}

我需要采取哪些步骤才能调用f1()和f2()函数?如何使用GCC正确地链接静态库?

目前为止,我尝试过:

gcc -lClient.a main.c 

这给了我:
ld: library not found for -lClient.a
collect2: ld returned 1 exit status

我认为那样做不行,你的目标程序可能需要使用C++。 - Karthik T
那么从C程序中调用C++功能就没有什么聪明的方法了吗? - user1068636
1
你可以将其封装为库内的一个函数。extern "C" void invoke_f1(); 并进行导出。 - Anthony
@user1068636 使用-lClient而不是-lClient.a来加载libClient.a - C. K. Young
1个回答

11

这样做行不通,或者至少不能实现可移植性。最明显的一点是将程序改为C++,这样你就可以访问那些特性了。

由于很明显的原因,你无法从C代码中“本地”使用C++代码。你没有访问面向对象特性的权限,所以很多东西都无法运行:构造函数、析构函数、移动/复制语义和虚拟继承可能是你会错过的最大的东西。(没错:除非它们有微不足道的构造函数和析构函数,否则你将无法正确创建或销毁对象。)

你还会遇到链接问题:C++函数名称被mangled成一个包含参数类型、返回类型和类的混乱字符串,看起来像__1cGstrcpy6Fpcpkc_0_。在C中声明函数的混淆名称是技术上可行的,或者使用dlsym获取指向它们的指针,但那简直是愚蠢的。别那么做。

如果你需要在C++中创建一个需要从C中调用的函数,你可以将其指定为extern "C",这样它的名称就不会被混淆,并且可以从C中访问,它本身也能够使用C++特性:
extern "C" void Foo()
{
    std::string hello = "Hello world!";
    std::cout << hello << std::endl;
}

然后你需要在程序的C端声明它,就像这样:

void Foo();

你可以通过在extern"C"函数中包装所有要公开给C程序的C++调用,并返回指向类型的指针并以此处理,但这种方式很快就会变得非常麻烦。你真的应该使用C++。

至于与静态库链接的问题,在Xcode中,进入项目设置,选择目标,转到“Build Phases”选项卡,展开“Link Binary With Libraries”部分,将你的.a文件拖放到那里即可。

而且,你将能够调用它。


1
这是正确的方法。如果应用程序必须使用 C 写成,而库必须使用 C++ 写成,无论出于什么原因,那么你需要将库接口代码封装到 C 可以理解的东西中。 - Anthony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接