2

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 SOCKET symbol to the linker/compiler by adding it to the symbol tree, and some how use dlsym() or similar to set it up.
  • Get the SOCKET information from socket.so to application.c so that application.c can store the return value of socket_connect without having to clutter down the main code with typedef's for SOCKET - since that's already done once in socket.c. And without a socket.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.

4
  • I don't believe you can import structure from DLL and compile it later without knowing structure. Compiler will not know the order. Commented Jul 27, 2017 at 11:04
  • If you want to create a library to be used by others, then always create a public header file which defines the things needed by the users of the library. You don't have to define complete structures, instead you could do something like the standard FILE opaque structure, where you have only e.g. typedef struct library_socket_structure SOCKET;. Then pass around pointers to this SOCKET type-name for your functions. Commented Jul 27, 2017 at 11:05
  • Oh and you should probably rename SOCKET to something else, since SOCKET is also the standard socket type in Windows. Commented Jul 27, 2017 at 11:05
  • 1
    Regarding the issue about "importing structures", that's not really possible. Once a translation unit have been compiled, things like structures doesn't really exist any more. All that's left of the structures are memory areas and offsets into them that the code reads from or writes to. The only way to get a structure is to keep debug information and somehow parse the structure out from it. Commented Jul 27, 2017 at 11:14

1 Answer 1

0

I don't think dlopen has anything to do with this... If you want a platform-independent socket-module, try something this:

/* 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 */

and then:

/* 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 */
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.