c - 在运行时从共享库导入结构 - 在编译时没有头文件

标签 c struct shared-libraries dllimport

当我尝试创建通用套接字 .so 库时,我很好奇。
我有一个平台定义的结构和一个如下所示的函数:

## == sock.c
#ifdef __unix__
    typedef int SOCKET;
#else
    typedef struct UNISock {
        _IN_ int af,
        _IN_ int type,
        _IN_ int protocol;
    } SOCKET;
#endif

SOCKET socket_connect(char * hostname, int portnumber) {
    #ifdef __unix__
        SOCKET connfd = 0;
    #else
        SOCKET connfd = INVALID_SOCKET; // Windows struct eq of "0"
    #endif

    ...

    return connfd;
}

然后我尝试从 application.c 导入和使用它。

## == application.c
typedef void* (*_func)();
int main(int argc, char *argv[]) {
    void* lib;
    _func socket_connect;
    _func init;

    lib = dlopen("./socket.so", RTLD_NOW|RTLD_GLOBAL);

    *(void**)(&socket_connect) = dlsym(lib, "socket_connect");
    *(void**)(&init) = dlsym(lib, "init");

    SOCKET connection = socket_connect("127.0.0.1", 1337);
}

很明显,我在这里没有遵循 C 的最佳实践,因为首先通常您会将这些结构/定义放在 .h 文件中,一切都很好。
但是我开始想知道我是否可以动态生成这个 struct,以及如何在 application.c 中设置它而没有在编译期间链接的头文件。

要么通过执行类似于 extern typedef int SOCKET; 的操作,然后使用 dlsym() 加载它。
(extern 显然会因 multiple storage classes in declaration specifiers 而失败,但这是我试图实现的想法的一个示例)

或者通过在我的套接字库中有一个返回 sizeof(SOCKET)init() 函数,这样我就可以使用 malloc()application.c 中为 SOCKET 在内存分配中需要的任何字节创建内存占位符并手动执行。

因为我不认识任何人在 C 中探索过这些东西 - 并且在线搜索线程似乎没有提供关于该主题的信息,除了将我链接到维基百科上的不同病毒类别。
或者一些 threads完全避免从库函数返回值。

所以我问一个模糊的问题,希望有人知道如何:

  • 通过将 struct SOCKET 符号添加到符号树中,将其保留/公开给链接器/编译器,以及一些如何使用 dlsym() 或类似方法进行设置的方法.
  • socket.so获取SOCKET信息到application.c,以便application.c可以存储socket_connect 的返回值,而不必使用 typedefSOCKET 将主代码搞乱 - 因为这已经在 中完成了一次套接字.c。并且没有 socket.h - 因为目标是解决对头文件的需求。
  • 无需在主应用程序代码中预先定义可能的数百个 struct/typedef 信息即可处理库函数返回值的任何替代方法。

我知道这倾向于 OOP,而且它又不是传统的 C。它既丑陋又不是任何理智的人会做的事情,因为 C 是 .如果这个问题有点离题或冒犯了所有程序员,我深表歉意。

最佳答案

我不认为 dlopen 与此有任何关系......如果你想要一个平台无关的套接字模块,试试这个:

/* ownsocket.h */

/* opaque type-definition */
typedef struct OwnSocket OwnSocket;

/* constructors */
OwnSocket *newServerSocket (int port);
OwnSocket *newClientSocket (const char *ptnhost, int ptnport);
OwnSocket *acceptClient (OwnSocket *server);
/* other constructors */
...
/* destructor */
closeSocket (OwnSocket *);

/* other operations */

然后:

/* ownsocket.c */

#include "ownsocket.h"

struct OwnSocket {
    int type; /* -1/0/1/2 = closed/client/listening_server/sub_server */
    ...
#ifdef __unix__
    int handle;
#else
    SOCKET handle;
#endif
    ...
};

/* implementation of functions */

关于c - 在运行时从共享库导入结构 - 在编译时没有头文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45348806/

相关文章:

c - 为什么这个倒转句算法不起作用?

c++ - 删除结构中的第一个元素

c - 链接共享库后符号丢失

java - 使用库时出现 ClassNotFoundException 异常

"#pragma omp parallel for "可以在循环内使用吗?

c++ - 多平台库设计。最佳实践

c - C语言中的_Space是什么意思?

c - `restrict` 关键字隐含的严格别名级别是什么?

c - configure --disable-shared 是否适用于 tcl 8.6.3?需要静态libtcl8.6.a

c - 质量分析控制疑点