C++问题,关于LIB库文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++问题,关于LIB库文件相关的知识,希望对你有一定的参考价值。

众所周知LIB库文件存有函数的实例,请问这个LIB库应该怎样生成?
例如:我有一个.h的头文件中含有ABC函数的声明。一个cpp文件含有ABC函数的定义,我想把cpp文件变成向LIB库文件一样可以用LIB库导入的方法导入的,应该怎样做?
2楼说的是动态连接库或静态连接库吧?

如果你的程序是动态链接库类型,而不是可执行文件,它就自动会生成一个.lib文件(静态库)。

下面来看看如何生成静态库。
我们知道静态库也称档案库,在此档案文件中实际上是收集了一系列的目标文件。这
些目标文件就是由cc(gcc)函数的源代码编译生成的。因此,静态库的生成方法实际上
可以分成两步:
1.将各函数代码所在的源文件编译成目录文件。例如,对于myfunc.c,可以用如下命令
将其编译成目标文件:
gcc -c myfunc.c
当然在有多个源文件时,只需在gcc 命令行中将其分别列上就可以了。
经此一步我休养将能够得到各源文件的目标文件。对上例,将得到myfunc.o
2.将各目标文件收集起来放到一个静态库文件中。这主要借助于ar命令完成,如:
ar r ~/lib/libtest.a myfunc.o

建立动态链接库、并不需要用到其他的工具,借助于gcc命令即可完成。此时需在命令
行中加上-K PIC和-G这两个选项,如下我们可以建立libtest的动态版本:
gcc -K PIC -G -o $HOME/lib/libtest.so myfunc.c

本来格式很好看的,但因为要贴到这里所以
扭曲了不少,见谅见谅。这里给的是linux下的例子,
但是solaris下的也差不多,如果你发现不同,就给
个详细说明出来,好不好。

ldd filename就可以看到程序用到哪些库。

ld -o OUTPUT /lib/crt0.o hello.o -lc
ld将输出最终结果文件 OUTPUT ,
用到/lib/crt0.o hello.o以及libc.a
libc.a来自标准库搜索路径,请参看-l选项的讨论

ld的选项顺序任意,可以重复,后面的将覆盖前面的。

gcc -c -fPIC linuxlib.c -O3 -o linuxlib.o
gcc -shared -Wl,-soname,liblinuxlib.so.1 \
-O3 -o liblinuxlib.so.1.0 linuxlib.o
(
ld -m elf_i386 -shared -o liblinuxlib.so.1.0 \
-soname liblinuxlib.so.1 linuxlib.o
这个语句产生的文件更小,不知道二者有何区别
-o liblinuxlib.so.1.0 这个文件名任意,关键是后面
两个符号连接要正确
当然推荐使用有意义的带版本信息的名字,包括
-soname liblinuxlib.so.1
)
ln -sf liblinuxlib.so.1.0 liblinuxlib.so.1
(
运行时,dynamic linker根据 -soname \
liblinuxlib.so.1 去寻找liblinuxlib.so.1
)
ln -sf liblinuxlib.so.1 liblinuxlib.so
(
编译的最后一个步骤,ld命令根据 -llinuxlib
选项去寻找liblinuxlib.so
)
export LD_LIBRARY_PATH=.
(
编译时、运行时都需要这个变量的存在
编译时如果不存在这个变量,编译依旧通过,但
用ldd查看会发现没有动态连接信息
运行时如果不存在这个变量,将报告无法找到动态连接库

这个变量如果不用相对路径".",换了运行环境就比较麻烦
export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
)
gcc -L. -lbsd -llinuxlib -O3 -o linuxkiller linuxkiller.c
(
-L. 指出除标准库搜索路径之外的库搜索路径,如果不指
定,将找不到liblinuxlib.so
这个选项并不能代替 LD_LIBRARY_PATH 变量,否则虽然编译通过,
但用ldd linuxkiller的时候会发现没有动态连接信息
)

可以把自己的动态连接库放到/usr/lib或者/lib下去,或者
修改/etc/ld.so.conf
然后利用/sbin/ldconfig。具体请man ldconfig

--

发信人: hellguard (小四), 信区: Unix
标 题: Re: help :static library----what's wrong--Thanks.
发信站: BBS 水木清华站 (Thu Aug 16 14:22:39 2001)

【 在 hululu (呼噜噜~回家中) 的大作中提到: 】
: I am building a static library. But I do not know what is
: wrong. Below is a sample:
: tt.c:
: #i nclude <stdio.h>
: int func()
: printf("func test\n");
: return 0;
:
: ii.c:
: #i nclude <stdio.h>
: extern int func();
: ...................
★ 生成静态链接库举例

1. vi demo.h
void demo ( void );

vi demo.c
#i nclude <stdio.h>
#i nclude "demo.h"
void demo ( void )

printf( "hello world\n" );
return;


2. g++ -Wstrict-prototypes -Wall -Wunused -O3 -c demo.c -o demo.o
file demo.o

3. ar -rsv libdemo.a demo.o
a - demo.o
file libdemo.a
nm -s libdemo.a
ar -tv libdemo.a
4. vi scz.c
#i nclude <stdio.h>
#i nclude "demo.h"
int main ( int argc, void * argv[] )

demo();
return 0;


5. g++ scz.c -L. -ldemo -Wstrict-prototypes -Wall -Wunused -O3 -o scz
参考技术A 这个问题很简单。先把你要做成LIB库文件的.cpp扩展文件保存,新建一个Win32StaticLibrary工程然后把你的.CPP文件加入到工程中,点编译编译成.lib库,这样就OK了可以在DEBUG文件夹中找到,以上方法使用VC6.0本回答被提问者采纳 参考技术B 用动态连接库吧,将你的ABC函数作为DLL的导出函数,编译后便回生成一个.dll和一个.lib文件,.lib文件中便是你导出函数的声明,你可一看看动态链接库方面的知识,不难 参考技术C 很简单以vc2003为例。
新建项目类型为win32项目,在应用程序设置里面选静态库就ok。
然后你就可以写程序了。
编译完成后要用的时候要包含头文件也要连接库文件。
用#pragma comment(lib,"*.lib")
参考技术D 如果你的c文件是prog.c
那么
$gcc -c prog.c -Wall -O2
会生成prog.o文件,
如果是生成静态库
$ar ru libprog.a prog.o

尽管链接到带有导​​出符号的 .lib 文件,但从托管 C++ 链接到非托管 C++ 时出现链接错误

【中文标题】尽管链接到带有导​​出符号的 .lib 文件,但从托管 C++ 链接到非托管 C++ 时出现链接错误【英文标题】:Link error linking from managed to unmanaged C++ despite linking to .lib file with exported symbols 【发布时间】:2012-07-17 22:23:06 【问题描述】:

尽管关注了各种关于从 C++/CLI 包装器 dll 使用和链接到非托管 C++ 代码的帖子,但我无法解决这些链接问题。

1>MyClassAdapter.obj : error LNK2028: unresolved token (0A00000A) "public: __thiscall MyClass::~MyClass(void)" (??1MyClass@@$$FQAE@XZ) referenced in function "public: void * __thiscall MyClass::`scalar deleting destructor'(unsigned int)" (??_GMyClass@@$$FQAEPAXI@Z)
1>MyClassAdapter.obj : error LNK2028: unresolved token (0A00000B) "public: __thiscall MyClass::MyClass(void)" (??0MyClass@@$$FQAE@XZ) referenced in function "public: __clrcall WrapperLayer::MyClassAdaptor::MyClassAdaptor(void)" (??0MyClassAdaptor@WrapperLayer@@$$FQ$AAM@XZ)
1>MyClassAdapter.obj : error LNK2019: unresolved external symbol "public: __thiscall MyClass::MyClass(void)" (??0MyClass@@$$FQAE@XZ) referenced in function "public: __clrcall WrapperLayer::MyClassAdaptor::MyClassAdaptor(void)" (??0MyClassAdaptor@WrapperLayer@@$$FQ$AAM@XZ)
1>MyClassAdapter.obj : error LNK2019: unresolved external symbol "public: __thiscall MyClass::~MyClass(void)" (??1MyClass@@$$FQAE@XZ) referenced in function "public: void * __thiscall MyClass::`scalar deleting destructor'(unsigned int)" (??_GMyClass@@$$FQAEPAXI@Z)

我有一个带有简单类的非托管本机 C++ dll,相应地导出/导入符号

// MyClass.h
#ifdef _EXPORTING
   #define DLL_PUBLIC __declspec(dllexport)
#else
   #define DLL_PUBLIC __declspec(dllimport)
#endif

class DLL_PUBLIC MyClass  . . . ;

我可以看到构建后生成的 .dll 和 .lib 链接器文件。

然后我有托管的 C++/CLI 包装器项目(也是一个 dll),它链接到 Linker->Input->Additional Dependencies 设置中的 MyClass.lib。在包装项目中还包含了来自 MyClass 的 .h 文件,我可以看到 sln 可以看到 MyClass.h 文件。

// MyClassAdaptor.h

#include "MyClass.h"

namespace WrapperLayer

    public ref class MyClassAdaptor 
     
      . . . 
    private:
        MyClass* _myclass;  
    ; 

可能缺少什么?

【问题讨论】:

非托管代码也是用 VC++ 2010 构建的吗? 所以,愚蠢的问题,但是...您实际上已经实现构造函数和析构函数,对吧? 是的,我为 MyClass 和 MyClassWrapper 都做过。编译器会不会只看到 MyClass.lib 而看不到 MyClass.dll? 【参考方案1】:

几点:

对 DLL 使用 Dependency Walker 并检查这些符号是否确实在 DLL 中。 确保您使用的是正确的 lib 文件 - 32 位 LIB 不能用于 64 位构建。 确保用于构建类的 .CPP 文件实际上是非托管文件(或 DLL 本身作为一个整体是非托管文件)。

【讨论】:

非常感谢!!依赖沃克太棒了!这确实是由于 32 位/64 位不匹配,因为我使用 Cmake 为 MyClass 生成 sln/project 文件并选择了不匹配的版本。如果没有 Dependency Walker,我将无法判断。

以上是关于C++问题,关于LIB库文件的主要内容,如果未能解决你的问题,请参考以下文章

从 c# 访问 C++ .lib 库

C++ 如何加载lib

在非启动项目中使用 lib 文件,在 c++ 解决方案中

C++ 可执行文件是不是包括 .obj、.lib 和 .dll?

Visual Studio C++ Link1104 无法打开文件 MSVCURTD.lib

如何 p/invoke 调用函数仅使用但 C++ 需要 .a/.lib/.o 文件?