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

时间:2017-07-27 10:57:15

标签: 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,但它是我想要实现的想法的一个例子)

或者在我的套接字库中使用init()函数返回sizeof(SOCKET),以便我可以在malloc()中使用application.c为任何字节创建内存占位符{ {1}}需要在内存分配中手动完成。

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

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

  • 通过将SOCKET符号添加到符号树中来保留/显示链接器/编译器,以及如何使用struct SOCKET或类似设置来设置它。
  • dlsym()获取SOCKET个信息至socket.so,以便application.c可以存储application.c的返回值,而不必使主代码混乱socket_connect的{​​{1}} - 因为typedef已经完成了一次。没有SOCKET - 因为目标是解决头文件的需求。
  • 处理库函数返回值的任何替代方法,而无需在主应用程序代码中预先定义数百个socket.c / typedef信息。

我知道这是倾向于OOP而且,它再次不是传统的C.它既丑陋又不是任何理智的人会做的事情,因为C是a。如果这个问题是临界主题或者冒犯每个程序员,我会道歉。

1 个答案:

答案 0 :(得分:0)

我认为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 */