当我尝试创建通用套接字 .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
的返回值,而不必使用typedef
的SOCKET
将主代码搞乱 - 因为这已经在中完成了一次套接字.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/