Hola a todos:
estoy haciendo una aplicacion en c# donde quiero importar una dll ya creada en c++ pero al ejecutarla me da el error:
CitarNo se puede encontrar el punto de entrada denominado 'suma' en el archivo DLL 'DLL_lib.dll'.
el codigo de la dll es el siguiente:
.h
#ifdef DLL_LIB_EXPORTS
#define DLL_LIB_API __declspec(dllexport)
#else
#define DLL_LIB_API __declspec(dllimport)
#endif
// Clase exportada de DLL_lib.dll
class DLL_LIB_API CDLL_lib
{
private:
int a;
int b;
public:
CDLL_lib(void);
// TODO: agregar métodos aquí.
double multiplica();
int getA();
int getB();
void setA(int a);
void setB(int b);
};
DLL_LIB_API int suma(void);
extern DLL_LIB_API int nDLL_lib;
DLL_LIB_API int fnDLL_lib(void);
.cpp
#include "stdafx.h"
#include "DLL_lib.h"
#ifdef _MANAGED
#pragma managed(push, off)
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
// Ejemplo de variable exportada
DLL_LIB_API int nDLL_lib=0;
// Ejemplo de función exportada.
DLL_LIB_API int fnDLL_lib(void)
{
return 42;
}
DLL_LIB_API int suma(void)
{
return 5+5;
}
// Constructor de clase exportada.
// Consultar DLL_lib.h para definir la clase
CDLL_lib::CDLL_lib()
{
this->a = 0;
this->b = 0;
}
int CDLL_lib::getA()
{
return a;
}
int CDLL_lib::getB()
{
return b;
}
void CDLL_lib::setA(int a)
{
this->a = a;
}
void CDLL_lib::setB(int b)
{
this->b = b;
}
double CDLL_lib::multiplica()
{
return (double)a*b;
}
y el archivo .cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace app_usa_dll
{
class Program
{
/// <summary>
/// Punto de entrada principal para la aplicación.
/// </summary>
[STAThread]
[DllImport(/*" ..\\..\\..\\debug\\*/"DLL_lib.dll")]
public static extern int suma();
[DllImport(/*" ..\\..\\..\\debug\\*/"DLL_lib.dll")]
public static extern void setA(int a);
[DllImport(/*" ..\\..\\..\\debug\\*/"DLL_lib.dll")]
public static extern void setB(int b);
[DllImport(/*" ..\\..\\..\\debug\\*/"DLL_lib.dll")]
public static extern double multiplica();
[DllImport(/*" ..\\..\\..\\debug\\*/"DLL_lib.dll")]
public static extern int getA();
[DllImport(/*" ..\\..\\..\\debug\\*/"DLL_lib.dll")]
public static extern int getB();
static void Main()
{
int a = 0;
int b = 0;
double c = 0;
int res = 0;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//funciones de la dll
try
{
/*a = setA(int.Parse(textBox3.Text));
b = setB(int.Parse(textBox2.Text));
c = multiplica();*/
res = suma();
setA(int.Parse("5"));
a = getA();
setB(int.Parse("6"));
b = getB();
c = multiplica();
res = suma();
}
catch (DllNotFoundException exc)
{
Console.WriteLine(exc.ToString());
}
catch (EntryPointNotFoundException exc)
{
Console.WriteLine(exc.ToString());
}
Application.Run(new Form1(a, b, c, res));
}
}
}
Alguna idea?¿
Gracias a todos
Te falta el .def
Sería algo como:
DLL_lib.def
LIBRARY DLL_lib
EXPORTS
CDLL_lib
getA
getB
etc
[/pre]
Por lo demás parece todo correcto, saludos!
mmm he probado a hacer lo dices, MazarD y me tira:
Citarerror LNK2001: símbolo externo CDLL_lib sin resolver d:\Documents and Settings\Ruben\Visual Studio 2005\Projects\DLL_CS\DLL_lib\DLL_lib.def
en la linea 1
archivo .def
LIBRARY DLL_lib
EXPORTS
CDLL_lib
getA
getB
setA
setB
multiplica
suma
:-[
Creo que no puedes exportar el constructor, no estoy seguro ya que nunca he tenido la necesidad.
Porqué no pones el contenido del constructor en el DllMain process_attach que es el punto en el que se supone debes realizar las tareas de inicialización?
O creas una función privada que haga lo mismo que el constructor y lo llamas desde process_attach.
O creas una función pública exportada pero que no sea constructor, que se llame Init y te aseguras de que deba ser llamada desde el programa que cargue la dll.
Si te paras a pensar no tiene mucho sentido tener constructor en una dll ya que no vas a poder de forma directa instanciar un objeto que vaya a llamarlo.
Saludos!
Ya elimine el constructor de la declaracion y compila sin problemas, pero sigue dando el error de que no encuentra el punto de entrada.... :-\ el archivo .def tengo que hacer algo mas cn el?algun include o algo asi o solo con crearlo basta??
Saludos
Ya un poco extrañado he decidido probarlo y a mi me funciona bien, la única diferencia con tu código es que todos mis archivos se llaman 'prova' y el nombre de la clase también claro.
Entonces una vez corriendo tendrás el problema de que setA y setB no te funcionarán puesto que utiliza this cuando en realidad no es una instancia del objeto, esto es porque desde c# declaras (estas obligado) la función como static cuando en realidad necesariamente debe ser miembro del objeto para poder acceder al valor de las variables para la instancia (this->a o this->b).
Probablemente este es el porque no se ven dlls con clases, no tiene mucho sentido si no vas a poder instanciar la clase desde el lenguaje que la utiliza.
Yo creo que tienes dos opciones, declarar static a y b o directamente pasar de la clases y hacerlo Cstyle x)
Te dejo tu código con las modificaciones que he hecho para que funcione.
Saludos!
prova.def:
LIBRARY prova
EXPORTS
getA
getB
setA
setB
multiplica
suma
nDLL_lib
fnDLL_lib
#define DLL_LIB_EXPORTS
#ifdef DLL_LIB_EXPORTS
#define DLL_LIB_API __declspec(dllexport)
#else
#define DLL_LIB_API __declspec(dllimport)
#endif
DLL_LIB_API double multiplica();
DLL_LIB_API int getA();
DLL_LIB_API int getB();
DLL_LIB_API void setA(int a);
DLL_LIB_API void setB(int b);
DLL_LIB_API int suma(void);
DLL_LIB_API int nDLL_lib=0;
DLL_LIB_API int fnDLL_lib(void);
#include "stdafx.h"
#include "prova.h"
int a;
int b;
#ifdef _MANAGED
#pragma managed(push, off)
#endif
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
a=0;
b=0;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#ifdef _MANAGED
#pragma managed(pop)
#endif
// Ejemplo de función exportada.
DLL_LIB_API int fnDLL_lib(void)
{
return 42;
}
int suma(void)
{
return 5+5;
}
int getA()
{
return a;
}
int getB()
{
return b;
}
void setA(int pa)
{
a = pa;
}
void setB(int pb)
{
b = pb;
}
double multiplica()
{
return (double)a*b;
}
WindowsApplication1 c#
[STAThread]
[DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
public static extern int suma();
[DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
public static extern void setA(int a);
[DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
public static extern void setB(int b);
[DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
public static extern double multiplica();
[DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
public static extern int getA();
[DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
public static extern int getB();
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(suma().ToString());
setA(11);
setB(11);
MessageBox.Show(multiplica().ToString());
MessageBox.Show(getA().ToString());
MessageBox.Show(getB().ToString());
}
perfecto.
muchas gracias xla ayuda!! :D