Скомпилируйте DLL в C/С++, затем вызовите ее из другой программы - программирование
Подтвердить что ты не робот

Скомпилируйте DLL в C/С++, затем вызовите ее из другой программы

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

Создайте DLL, которая экспортирует некоторые функции, например

int add2(int num){
   return num + 2;
}

int mult(int num1, int num2){
   int product;
   product = num1 * num2;
   return product;
}

Я компилирую с помощью MinGW, я бы хотел сделать это на C, но если есть какие-то реальные различия в С++, я бы тоже хотел это знать. Я хочу знать, как загрузить эту DLL в другую C (и С++) программу, а затем вызывать эти функции из нее. Моя цель здесь, немного поиграв с DLL, - сделать VB-интерфейс для кода C (++), загрузив библиотеки DLL в visual basic (у меня есть visual studio 6, я просто хочу сделать некоторые формы и события для объектов на тех формах, которые вызывают DLL).

Мне нужно знать, как вызвать gcc (/g++), чтобы он создавал DLL, но также как писать (/generate) файл экспорта... и то, что я могу/не могу сделать в DLL (например, могу ли я принимать аргументы указателем/ссылкой из front-end VB? Может ли DLL вызвать теоретическую функцию в интерфейсе? Или иметь функцию "указатель функции" (я даже не знаю, возможно ли это) от VB и назовите его?) Я уверен, что не могу передать вариант DLL... но это все, что я действительно знаю.

снова обновить

Хорошо, я выяснил, как скомпилировать его с помощью gcc, чтобы запустить DLL

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a

а затем у меня была другая программа, загружающая его и проверяющая функции, и она отлично работала, Большое спасибо за совет, но я попробовал загрузить его с помощью VB6, вроде этого

Public Declare Function add2 Lib "C:\c\dll\mydll.dll" (num As Integer) As Integer

то я просто вызвал add2 (text1.text) из формы, но это дало мне ошибку времени выполнения:

"Не удается найти точку входа DLL add2 в C:\c\dll\mydll.dll"

это код, который я скомпилировал для DLL:

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

EXPORT int __stdcall add2(int num){
  return num + 2;
}

EXPORT int __stdcall mul(int num1, int num2){
  return num1 * num2;
}

вызывал его из программы C, как это сработало, хотя:

#include<stdio.h>
#include<windows.h>

int main(){

  HANDLE ldll;
  int (*add2)(int);
  int (*mul)(int,int);

  ldll = LoadLibrary("mydll.dll");
  if(ldll>(void*)HINSTANCE_ERROR){
    add2 = GetProcAddress(ldll, "add2");
    mul = GetProcAddress(ldll, "mul");
    printf("add2(3): %d\nmul(4,5): %d", add2(3), mul(4,5));
  } else {
    printf("ERROR.");
  }

}

любые идеи?

решил

Чтобы решить предыдущую проблему, мне просто пришлось скомпилировать ее так:

gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias

и использовать этот вызов API в VB6

Public Declare Function add2 Lib "C:\c\dll\mydll" _
    (ByVal num As Integer) As Integer

Я научился не забывать явно указывать ByVal или ByRef - я просто возвращал адрес аргумента, который я передал, он выглядел как -3048.

4b9b3361

Ответ 1

Что касается построения DLL с использованием MinGW, вот несколько очень коротких инструкций.

Сначала вам нужно пометить свои функции для экспорта, чтобы их можно было использовать вызывающими DLL. Чтобы сделать это, измените их так, чтобы они выглядели (например)

__declspec( dllexport ) int add2(int num){
   return num + 2;
}

тогда, если ваши функции находятся в файле funcs.c, вы можете скомпилировать их:

gcc -shared -o mylib.dll funcs.c

Флаг -shared указывает gcc создать DLL.

Чтобы проверить, действительно ли DLL экспортировала функции, воспользуйтесь свободным инструментом Code:: Blocks, который отлично работает с MinGW.

Изменить: Подробнее об этом можно узнать в статье Создание библиотеки MinGW для использования с Visual Basic на Wiki MinGW.

Ответ 2

Вот как вы это делаете:

В .h

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

extern "C" // Only if you are using C++ rather than C
{    
  EXPORT int __stdcall add2(int num);
  EXPORT int __stdcall mult(int num1, int num2);
}

в .cpp

extern "C" // Only if you are using C++ rather than C
{    
EXPORT int __stdcall add2(int num)
{
  return num + 2;
}


EXPORT int __stdcall mult(int num1, int num2)
{
  int product;
  product = num1 * num2;
  return product;
}
}

Макрос сообщает вашему модулю (т.е. ваши файлы .cpp), что они предоставляют материал dll для внешнего мира. Люди, которые заявляют о вашем файле .h, хотят импортировать те же функции, поэтому они продают EXPORT, как сообщая компоновщику для импорта. Вам нужно добавить BUILD_DLL в параметры компиляции проекта, и вы можете переименовать его в нечто явно специфичное для вашего проекта (в случае, если dll использует вашу dll).

Вам также может понадобиться создать файл . def для переименования функций и де-обфускации имен (C/С++ управляет этими именами), Эта запись в блоге может быть интересной отправной точкой в ​​этом вопросе.

Загрузка ваших собственных DLL файлов аналогична загрузке системных DLL файлов. Просто убедитесь, что DLL находится на вашем системном пути. C:\windows\или рабочий каталог вашего приложения - это простое место для размещения вашей DLL.

Ответ 3

Есть только одно отличие. Вы должны позаботиться или назвать mangling выиграть С++. Но на окнах вам нужно позаботиться о 1) дефрагментировать функции, которые будут экспортироваться из DLL 2) напишите так называемый файл .def, в котором перечислены все экспортированные символы.

В Windows при компиляции библиотеки DLL необходимо использовать

__ declspec (dllexport)

но при его использовании вы должны написать __declspec (DllImport)

Таким образом, обычный способ сделать это - это что-то вроде

#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif

Именование немного запутанно, потому что его часто называют EXPORT. Но это то, что вы найдете в большинстве заголовков где-то. Поэтому в вашем случае вы должны написать (с указанным выше #define)

int DLL_EXPORT добавить.... int DLL_EXPORT mult...

Помните, что при создании разделяемой библиотеки необходимо добавить директиву Preprocessor BUILD_DLL.

Отношения Friedrich

Ответ 4

Вещь, которую следует учитывать при написании библиотек С++, называется mangling. Если вам нужна интероперабельность между C и С++, вам будет лучше, экспортируя неподдерживаемые функции C-стиля из DLL.

У вас есть два варианта использования dll

  • Либо используйте файл lib для ссылки на символы - компиляция динамической компоновки времени
  • Используйте LoadLibrary() или какую-либо подходящую функцию для загрузки библиотеки, получения указателя функции (GetProcAddress) и вызова ее - динамической компоновки времени выполнения

Экспорт классов не будет работать, если вы следуете второму методу.

Ответ 5

Для VB6:

Вам нужно объявить свои C-функции как __stdcall, иначе вы получите ошибки типа "недействительный вызов". О других ваших вопросах:

Могу ли я принимать аргументы указателем/ссылкой из VB-интерфейса?

Да, используйте модификаторы ByRef/ByVal.

Может ли DLL вызвать теоретическую функцию в интерфейсе?

Да, используйте оператор AddressOf. Вам нужно передать указатель функции на dll раньше.

Или у функции есть "указатель функции" (я даже не знаю, возможно ли это) от VB и называть его?)

Да, используйте оператор AddressOf.

обновление (появилось больше вопросов)):

чтобы загрузить его в VB, я просто делаю обычный метод (что бы я сделал для загрузки winsock.ocx или какой-то другой среды выполнения, но вместо этого нашел свою DLL), или я ставлю вызов API в модуль?

Вам нужна функция decaler API в коде VB6, например следующее:

Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
   (ByVal hwndOwner As Long, _
    ByVal nFolder As Long, _
    ByRef pidl As Long) As Long