I got curious when I tried to create a general purpose socket .so library.
I have a platform defined struct and a function that looks like:
## == 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;
}
Which I then try to import and use from 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);
}
Obviously I'm not following C's best practices here since - well first of all normally you'd place these structs/definitions in a .h file and all is well.
But I started to wonder if I could produce this struct on the fly, and some how set it up in application.c without a header file that was linked during compilation.
Either by doing something similar to extern typedef int SOCKET; and use dlsym() to load it.
(extern will fail with multiple storage classes in declaration specifiers obviously, but it's an example of the idea I'm trying to achieve)
Or by having a init() function in my socket library that returned the sizeof(SOCKET) so that I could use malloc() in application.c to create a memory placeholder for whatever bytes SOCKET will need in memory allocation and do it manually.
Since I don't know anyone that's explored these things in C - and searching for threads online appears to give no information on the topic except link me to different virus categories on Wikipedia.
Or some threads avoids return values completely from library functions.
So I'm asking a vague question in hopes that someone knows how to:
- Keep/Expose the
struct SOCKETsymbol to the linker/compiler by adding it to the symbol tree, and some how usedlsym()or similar to set it up. - Get the
SOCKETinformation fromsocket.sotoapplication.cso thatapplication.ccan store the return value ofsocket_connectwithout having to clutter down the main code withtypedef's forSOCKET- since that's already done once insocket.c. And without asocket.h- because the goal is to work around the need for a header file. - Any alternative ways to handle return values from library functions without pre-defining the potentially hundreds of
struct/typedef information in main application code.
I get that this is leaning towards OOP and that, again, it's not traditional C. It's both ugly and not something anyone sane person would do since C is a . And I apologize if this questions is borderline Off Topic or offends every programmer ever.
FILEopaque structure, where you have only e.g.typedef struct library_socket_structure SOCKET;. Then pass around pointers to thisSOCKETtype-name for your functions.SOCKETto something else, sinceSOCKETis also the standard socket type in Windows.