Nano Hash - криптовалюты, майнинг, программирование

Импортировать структуру из общей библиотеки во время выполнения - без файла заголовка во время компиляции

Мне стало любопытно, когда я попытался создать библиотеку сокетов общего назначения .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);
}

Очевидно, я здесь не следую передовым методам языка Си, поскольку - ну, прежде всего, обычно вы помещаете эти структуры / определения в файл .h, и все в порядке.
Но я начал задаваться вопросом, смогу ли я создать этот struct на fly, и кое-как настроить его в application.c без файла заголовка, который был связан во время компиляции.

Либо сделав что-то похожее на extern typedef int SOCKET; и загрузив его с помощью dlsym().
(extern, очевидно, потерпит неудачу с multiple storage classes in declaration specifiers, но это пример идеи, которую я пытаюсь реализовать)

Или имея функцию init() в моей библиотеке сокетов, которая возвращала sizeof(SOCKET), чтобы я мог использовать malloc() в application.c для создания заполнителя памяти для любых байтов, которые SOCKET потребуются при распределении памяти, и делать это вручную.

Поскольку я не знаю никого, кто исследовал бы эти вещи на C - и поиск тем в Интернете, похоже, не дает никакой информации по теме, кроме ссылки на разные категории вирусов в Википедии.
Или некоторые threads полностью избегает возвращаемых значений из библиотечных функций.

Поэтому я задаю расплывчатый вопрос в надежде, что кто-то знает, как:

  • Сохраните / предоставьте символ struct SOCKET компоновщику / компилятору, добавив его в дерево символов, и каким-то образом используйте dlsym() или подобное для его настройки.
  • Получите SOCKET информацию от socket.so до application.c, чтобы application.c мог сохранить возвращаемое значение socket_connect без необходимости загромождать основной код typedef для SOCKET - поскольку это уже было сделано один раз в socket.c. И без socket.h - потому что цель состоит в том, чтобы обойти необходимость в файле заголовка.
  • Любые альтернативные способы обработки возвращаемых значений из библиотечных функций без предварительного определения потенциально сотен struct / typedef информации в основном коде приложения.

Я понимаю, что это склоняется к ООП и, опять же, это не традиционный C. И я прошу прощения, если этот вопрос выходит за рамки темы или оскорбляет любого программиста.


  • Я не верю, что вы можете импортировать структуру из DLL и скомпилировать ее позже, не зная структуры. Компилятор не знает порядка. 27.07.2017
  • Если вы хотите создать библиотеку для использования другими, всегда создавайте общедоступный файл заголовка, который определяет вещи, необходимые пользователям библиотеки. Вам не нужно определять полные структуры, вместо этого вы можете сделать что-то вроде стандартной непрозрачной структуры FILE, где у вас есть только, например, typedef struct library_socket_structure SOCKET;. Затем передайте указатели на это SOCKET имя-типа для ваших функций. 27.07.2017
  • Да, и вам, вероятно, следует переименовать SOCKET во что-то другое, поскольку SOCKET также является стандартным типом сокета в Windows. 27.07.2017
  • Что касается вопроса об импорте структур, это на самом деле невозможно. После компиляции единицы перевода, например структур на самом деле больше не существует. Все, что осталось от структур, - это области памяти и смещения в них, из которых код читает или записывает. Единственный способ получить структуру - сохранить отладочную информацию и каким-то образом выделить из нее структуру. 27.07.2017

Ответы:


1

Я не думаю, что 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 */
27.07.2017
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..