c++ - create - crear dll en c# visual studio 2017
Compila una DLL en C/C++, luego llámala desde otro programa (5)
Así es como lo haces:
En .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);
}
en .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;
}
}
La macro le dice a su módulo (es decir, sus archivos .cpp) que están proporcionando las cosas dll al mundo exterior. Las personas que incluyen su archivo .h desean importar las mismas funciones, por lo tanto, venden EXPORT y le dicen al vinculador que importe. Debe agregar BUILD_DLL a las opciones de compilación del proyecto, y es posible que desee cambiarle el nombre a algo obviamente específico de su proyecto (en caso de que un dll use su dll).
Es posible que también deba crear un archivo .def para cambiar el nombre de las funciones y des-ofuscar los nombres (C / C ++ modifica esos nombres). Esta entrada de blog puede ser un punto de partida interesante sobre eso.
Cargar sus propios dlls personalizados es como cargar dlls del sistema. Solo asegúrese de que la DLL se encuentre en la ruta de su sistema. C: / windows / o el directorio de trabajo de su aplicación son un lugar fácil para poner su dll.
Quiero hacer una DLL simple y simple que exporte una o dos funciones, luego intentar llamarlo desde otro programa ... En todas partes he visto hasta ahora, es para asuntos complicados, diferentes formas de vincular cosas, problemas extraños que Ni siquiera empecé a darme cuenta de que existe aún ... Solo quiero comenzar, haciendo algo como eso:
Cree una DLL que exporte algunas funciones, como
int add2(int num){
return num + 2;
}
int mult(int num1, int num2){
int product;
product = num1 * num2;
return product;
}
Estoy compilando con MinGW, me gustaría hacer esto en C, pero si hay diferencias reales al hacerlo en C ++, me gustaría saber cuáles también. Quiero saber cómo cargar esa DLL en otro programa C (y C ++), y luego llamar a esas funciones desde allí. Mi objetivo aquí, después de jugar un poco con las DLL, es crear un front-end de VB para código C (++), cargando DLL en Visual Basic (tengo Visual Studio 6, solo quiero crear algunas formas y eventos para los objetos en esos formularios, que llaman a la DLL).
Necesito saber cómo llamar a gcc (/ g ++) para que cree una DLL, pero también cómo escribir (/ generar) un archivo de exportación ... y lo que puedo / no puedo hacer en una DLL (por ejemplo, ¿puedo tomar argumentos por puntero / referencia del front-end de VB? ¿Puede el DLL llamar a una función teórica en el front-end? O tener una función tomar un "puntero de función" (ni siquiera sé si eso es posible) desde VB y llamar es?) Estoy bastante seguro de que no puedo pasar una variante a la DLL ... pero eso es todo lo que sé realmente.
actualizar de nuevo
De acuerdo, descubrí cómo compilarlo con gcc, para hacer el dll que ejecuté
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--out-implib,libmessage.a
y luego tuve otro programa cargarlo y probar las funciones, y funcionó muy bien, muchas gracias por el consejo, pero traté de cargarlo con VB6, como este
Public Declare Function add2 Lib "C:/c/dll/mydll.dll" (num As Integer) As Integer
entonces acabo de llamar a add2 (text1.text) de un formulario, pero me dio un error de tiempo de ejecución:
"No se puede encontrar el punto de entrada DLL add2 en C: / c / dll / mydll.dll"
este es el código que compilé para el 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;
}
llamarlo desde el programa C como esto funcionó, sin embargo:
#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.");
}
}
¿algunas ideas?
resuelto
Para resolver el problema anterior, solo tuve que compilarlo así:
gcc -c -DBUILD_DLL dll.c
gcc -shared -o mydll.dll dll.o -Wl,--add-stdcall-alias
y usa esta llamada API en VB6
Public Declare Function add2 Lib "C:/c/dll/mydll" _
(ByVal num As Integer) As Integer
Aprendí a no olvidarme de especificar ByVal o ByRef explícitamente - Estaba recuperando la dirección del argumento que aprobé, parecía que, -3048.
En cuanto a construir una DLL usando MinGW, aquí hay algunas instrucciones muy breves.
En primer lugar, debe marcar sus funciones para exportar, para que las personas que llaman de la DLL puedan usarlas. Para hacer esto, modifíquelos para que se vean como (por ejemplo)
__declspec( dllexport ) int add2(int num){
return num + 2;
}
luego, suponiendo que sus funciones se encuentran en un archivo llamado funcs.c, puede compilarlas:
gcc -shared -o mylib.dll funcs.c
La opción -shared indica a gcc que cree una DLL.
Para comprobar si la DLL realmente ha exportado las funciones, obtenga la herramienta gratuita Dependency Walker y úsela para examinar la DLL.
Para obtener un IDE gratuito que automatizará todos los indicadores, etc., necesarios para compilar DLL, eche un vistazo al excelente Code::Blocks , que funciona muy bien con MinGW.
Editar: para obtener más detalles sobre este tema, consulte el artículo Cómo crear una DLL MinGW para usar con Visual Basic en la Wiki MinGW.
Lo que hay que tener en cuenta al escribir C ++ dlls es cambiar el nombre. Si quieres interoperabilidad entre C y C ++, estarás mejor exportando funciones C-style no destrozadas desde el dll.
Tienes dos opciones para usar un dll
- Utilice un archivo lib para vincular los símbolos: compilar enlaces dinámicos de tiempo
- Use
LoadLibrary()
o alguna función adecuada para cargar la biblioteca, recuperar un puntero de función (GetProcAddress
) y llamarlo - enlace dinámico en tiempo de ejecución
La exportación de clases no funcionará si sigues el segundo método.
Para VB6:
Debes declarar tus funciones C como __stdcall, de lo contrario obtendrás errores de tipo "convención de llamadas inválidas". Sobre otras sus preguntas:
¿Puedo tomar argumentos por puntero / referencia del front-end de VB?
Sí, use modificadores ByRef / ByVal.
¿Puede el DLL llamar a una función teórica en el front-end?
Sí, use la instrucción AddressOf. Necesita pasar el puntero de función a dll antes.
O tener una función tomar un "puntero de función" (no sé si es posible) de VB y llamarlo?)
Sí, use la instrucción AddressOf.
actualización (aparecieron más preguntas :)):
para cargarlo en VB, ¿acabo de hacer el método habitual (lo que haría para cargar winsock.ocx o algún otro tiempo de ejecución, pero encontrar mi DLL en su lugar) o puse una llamada de API en un módulo?
Debes decalar la función API en el código VB6, como el siguiente:
Private Declare Function SHGetSpecialFolderLocation Lib "shell32" _
(ByVal hwndOwner As Long, _
ByVal nFolder As Long, _
ByRef pidl As Long) As Long
Solo hay una diferencia. Tienes que tener cuidado o nombrar Winning ganar C ++. Pero en Windows debe tener cuidado acerca de 1) declarar las funciones a exportar desde el DLL 2) escribir un archivo llamado .def que enumera todos los símbolos exportados.
En Windows durante la compilación de una DLL tiene que usar
__declspec (dllexport)
pero mientras lo usa debe escribir __declspec (dllimport)
Entonces, la forma habitual de hacerlo es algo así como
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
El nombre es un poco confuso, porque a menudo se llama EXPORTACIÓN ... Pero eso es lo que encontrará en la mayoría de los encabezados en algún lugar. Entonces en tu caso escribirías (con el #define arriba)
int DLL_EXPORT add .... int DLL_EXPORT mult ...
Recuerde que debe agregar la directiva de preprocesador BUILD_DLL durante la compilación de la biblioteca compartida.
Saludos Friedrich