linux gcc -链接多个共享库[重复]

dldeef67  于 2023-08-03  发布在  Linux
关注(0)|答案(1)|浏览(108)

此问题在此处已有答案

What is an undefined reference/unresolved external symbol error and how do I fix it?(39答案)
11天前关闭。

背景知识:

首先,我解释一下到目前为止我对这些gcc标志的理解:

-Lgcc手册中说明,此标志将指定目录“添加到要搜索的目录列表中-l
**-l:**再次按照手册所说的,“链接时搜索名为library的库”。

所以,我对这两个的理解是,第一个将目录添加到一个列表中,第二个将被链接器搜索到,并命名为library!

**-I对此,说明书上说:“将目录dir添加到在预处理期间搜索头文件的目录列表中”!所以我假设这一个和-L**一样,但是用于头文件。
-Wl-Wl部分向链接器发送逗号分隔的选项

我想做的是:

我想编译/构建一个使用3.so共享库的可执行文件;其中2个(libpqlibsqlite3)由官方第三方供应商(Postgresql和Sqlite)提供;并安装了apt install
第三个是我的;我自己写的,并试图将它与我的可执行文件链接,以便能够在运行时使用它。

目前为止我尝试的是:

如果我使用下面的命令编译我的代码,而不使用我自己的库(以及代码中的相应函数),它可以正常工作:

g++ -std=c++20 full.cpp -o loadTester -L/usr/include/postgresql/libpq -lpq -lsqlite3

字符串
然而,使用这些命令,也链接我自己的库与我的代码,我得到错误:

gcc -std=gnu17 -shared -o liblogwritter.so -fPIC logWritter.c
g++ -std=c++20 full-with-logger.cpp -o loadTester -L/usr/include/postgresql/libpq -L./ -lpq -lsqlite3 -llogwritter -Wl,-rpath=./ -I./


我还尝试用完整路径替换./部分:/home/username/Desktop/Current/ .

错误:

/usr/bin/ld: /tmp/ccSFD38J.o: in function `pgConncetionInit(char const*)':
full-with-logger.cpp:(.text+0xc3): undefined reference to `logWritter(char const*)'
/usr/bin/ld: /tmp/ccSFD38J.o: in function `pgInsertQuery(char**)':
full-with-logger.cpp:(.text+0x709): undefined reference to `logWritter(char const*)'
/usr/bin/ld: /tmp/ccSFD38J.o: in function `main':
full-with-logger.cpp:(.text+0x1994): undefined reference to `logWritter(char const*)'
/usr/bin/ld: full-with-logger.cpp:(.text+0x19e2): undefined reference to `logWritter(char const*)'
/usr/bin/ld: full-with-logger.cpp:(.text+0x1b0e): undefined reference to `logWritter(char const*)'
collect2: error: ld returned 1 exit status

库代码:

logWriter.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SV_SOCK_PATH "/tmp/shahab_logger"

int logWritter(const char* messageData)
{
    struct sockaddr_un addr;

    // Create a new client socket with domain: AF_UNIX, type: SOCK_STREAM, protocol: 0
    int sfd = socket(AF_UNIX, SOCK_STREAM, 0);

    // Construct server address, and make the connection.
    memset(&addr, 0, sizeof(struct sockaddr_un));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1);

    if (connect(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1)
    {
        fprintf(stderr, "Error connecting to server\n");
        return 0;                
    }

    write(sfd, messageData, strlen(messageData));

    close(sfd);
    return 0;
}

logWriter.h

#ifndef LOGWRITTER_H
#define LOGWRITTER_H
 
int logWritter(const char* messageData);
 
#endif  // LOGWRITTER_H

myprogram.cpp

... //Several lines removed

logWritter(jobExecTime.c_str());

... //Several lines removed

注意:

我为我的库做了一个简单的驱动程序,如下所示,它工作得很好(前提是我之前运行server.c来接受套接字连接):

#include <stdio.h>
#include <stdlib.h>
#include "logWritter.h"

int main()
{
    printf("Test driver program!\n");
    if (logWritter("Test driver program!") > 0)
    {
        printf("Error!\n");
        exit(1);
    }

    return 0;
}


我编译了这个驱动程序如下:

gcc -c -Wall -Werror -fpic logWritter.c
gcc -shared logWritter.o -o liblogwritter.so
gcc -Wall testDriver.c -o testDriver -L/home/username/Desktop/logger/ -llogwritter -Wl,-rpath=/home/username/Desktop/logger/

注2:

以下是/home/username/Desktop/Current/中的文件列表(所有文件都存在),以防万一:

activity_main.db  full.cpp  full-with-logger.cpp  liblogwritter.so  logServer
logWritter.c  logWritter.h  postgresInit.sql  run.sh  server.c  sqliteInit.sql  unix_socket.h

提问:

我认为在这一点上是显而易见的,在阅读了这么长的帖子之后(我对你的国王努力和时间的最大敬意和赞赏),但要遵循这里的标准:
1.我在第一节中解释的理解是正确的吗?
1.“我是什么人?”张晓飞问道。
1.我应该如何编译我的可执行文件?请解释这两种情况,我复制的头文件在/usr/include/和共享库文件在/usr/local/lib,或者如果我想从当前的工作文件夹链接它们,因为它是现在在上面的例子的情况下.

xj3cbfub

xj3cbfub1#

由于您在.c中定义了logWritter,因此在C++中使用时必须使用C链接声明它,因此logWriter.h必须是

#ifndef LOGWRITTER_H
#define LOGWRITTER_H
#ifdef __cplusplus
extern "C" {
#endif

int logWritter(const char* messageData);

#ifdef __cplusplus
}
#endif
#endif

字符串

相关问题