c/c++静态库之间相互调用的实战案例

本文主要介绍c语言写的项目如何调用c++实现的库和c++如何调用c语言实现的库 一、c++项目如何调用c的库(以静态库为例) ⛄️示例:建立一个项目Stack_

本文主要介绍c语言写的项目如何调用c++实现的库和c++如何调用c语言实现的库

一、c++项目如何调用c的库(以静态库为例)

⛄️示例:建立一个项目Stack_c.lib,将该项目中的栈的实现的代码打包为一个静态库,再建立另一个c++的项目,并调用打包好的c实现的静态库里的栈的相关函数

1.将栈的源文件和头文件拷贝一份到Stack_c.lib这个项目的路径下

2.打包成静态库

⛄️应用好之后就点击生成解决方案 ,之后就会生成一个Stack_c.lib的静态库了 (与项目名重名了,问题不大 不要在意)

生成后我们可以点开项目的所在目录下 找到debug目录 可以看到里面多了一个Stack_c.lib的静态库文件 表示打包成功!

⛄️至此,静态库就打包好了,当然是编译器帮我们打包的,后续会更新如何自己亲手打包一个库(动静态库的知识)!

3.建立一个c++项目(TestStacklib) 引入c项目中的头文件

注意:这里的引入头文件的路径可以是相对路径 其中是代表的上级目录 只需找到自己创建的动态库的头文件的路径并在新建的c++项目中包含即可

本文中的test.cpp是一段关于括号匹配的算法代码 可以用建的静态库里的栈的特性来解决

bool isValid(const char* s) {
    const char* cur = s;
    stack stack;
    StackInit(&stack);
    while (*cur != '\0')
    {
        if (*cur == '(' || *cur == '{' || *cur == '[')//如果是左括号就进栈
        {
            StackPush(&stack, *cur);
        }
        else
        {
            if (StackEmpty(&stack))//考虑到开始是右括号,那么就是栈为空,就不可能有效,直接返回FALSE
            {
                return false;
            }
            char top = StackTop(&stack);
            if (*cur == ')' && top == '(' || *cur == '}' && top == '{' || *cur == ']' && top == '[')
            {
                StackPop(&stack);
            }
            else {
                return false;
            }
        }
        cur++;
    }
    if (StackEmpty(&stack))//有可能只有一个左括号,进栈就没了,有效还有判断栈是否为空,为空才是有效括号
        return true;
    else
        return false;

}

int main()
{
    cout << isValid("{{))") << endl;
    cout << isValid("({})") << endl;
    return 0;
}

4.设置附加库和附属关系

将静态库中的debug目录的路径复制到附加库目录中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uwjKkcKk-1657719900201)(C:\Users\华哥\AppData\Roaming\Typora\typora-user-images\image-20220713195455905.jpg)]

到这里附加库目录的操作就完成了 接下来就是在输入中设置依赖项了

到此准备工作就完成了 接下来有两种方法可以实现c++项目调用c静态库

1.将stack_c.lib中的stack.c的后缀改成stack.cpp 即可
2.在c++项目中使用extern “C” 表示编译的时候按照c的规则编译链接(主要就是函数名修饰的规则用c的规则)因为c++是兼容c的所以c++的编译器可以这么干 反过来c是不可以兼容c++的 所以反过来是行不通的。

接着往下看:

第一种方法:将Stack_c.lib中的stack.c 改名为 stack.cpp(使得其编译链接的时候是按照c++的规则,这样c++项目调c++规则生成的库就可以理所当然的调动了,但是这样的方式似乎很不着调,本来是c库,但是硬是把里面的源文件的后缀改成了cpp 不太好)

然后运行那段代码就可以成功运行了 证明调用静态库成功!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Og8Njbtu-1657719900202)(C:\Users\华哥\AppData\Roaming\Typora\typora-user-images\image-20220713201637750.jpg)]

第二种:利用extern "C"改变c++项目的编译链接过程的规则由c++的规则变成c的规则,这样再调用c的静态库也就可以实现了,而且不用像第一种方法一样去改源文件的后缀(强盗行为)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYdV4ZeG-1657719900202)(C:\Users\华哥\AppData\Roaming\Typora\typora-user-images\image-20220713202155357.jpg)]

格式:

extern "C"
{
	#include"库的头文件路径"
}

之后就可以运行成功 ,表示链接成功了!就不贴图了 与上面的图一样

二、c项目如何调用c++的库(静态库为例)

还是那句话,c++兼容c 要用c项目调用c++库 那么就只能是让c++ 的库编译的时候用c的规则来,那么该咋弄呢?
还是extern “C”

1.建立c++项目(Stack_cpp) 并且将栈的源文件和头文件包含在该目录 将其打包为cpp的静态库

右击项目名称 点击属性 再更改配置类型为静态库类型

之后点击到项目的路径 进入debug目录 看到生成了一个Stack_cpp.lib 就说明生成打包静态库成功了!

接下来就是用extern "C"结合条件编译来使得c++项目中的代码按照c的规则来编译链接 但是c项目要包含c++静态库的头文件 那么就会在预处理的时候头文件展开 那么c项目中就也会有 extern “C” 这是不可以的 只有c++才可以识别extern “C” c是识别不了的 会报错!!!

那么如何解决 ? 条件编译这个时候就派上大用处了

c++ 的文件中天然包含 __cplusplus 标识符 而c是没有的 可以以此为入口点 通过条件编译使得extern “C” 在c++项目中展开 但是在c项目中不展开 就将问题解决了

下面还有一个简化版的条件编译

//简化版
#ifdef __cplusplus
extern "C"
{
#endif

 void StackInit(stack* pst);
 void StackDestory(stack* pst);
 void StackPush(stack* pst,STDataType x);
 void StackPop(stack* pst);
 bool StackEmpty(stack* pst);
 int StackSize(stack* pst);
 STDataType StackTop(stack* pst);

#ifdef __cplusplus
}
#endif

之后就是 建立c项目 然后 建立test.c 拷贝那段关于括号匹配的代码到其中 包含静态库的头文件 添加打包的cpp动态库到附加库目录 设置依赖项 通过调用cpp静态库里的栈的函数解决 运行成功就说明c项目链接c++的静态库成功

2.建立c项目

3.包含静态库的头文件

4 .添加打包的cpp动态库到附加库目录 设置依赖项

然后就大功告成了 ,如果没有差错就可以直接运行成功了。

这里需要注意的是 要记得使用静态库前完成了准备工作后一定要生成解决方案后再在来调用库!

总结

到此这篇关于c/c++静态库之间相互调用的文章就介绍到这了,更多相关c/c++静态库间相互调用内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!

您可能有感兴趣的文章
C++的替代:微软如何如何使用rust?

一篇关于如何使用rust调用c++静态库并编译nodejavascript包的问题

Java C++ 算法题解leetcode652寻找重复子树

Java C++题解eetcode940不同的子序列 II

Java C++刷题leetcode1106解析布尔表达式