importar dll de c++ en c#

Iniciado por ^kazike^, 9 Septiembre 2009, 18:03 PM

0 Miembros y 1 Visitante están viendo este tema.

^kazike^

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

MazarD

Te falta el .def
Sería algo como:

DLL_lib.def
Código (cpp) [Seleccionar]
LIBRARY DLL_lib
EXPORTS
CDLL_lib
getA
getB
etc
[/pre]

Por lo demás parece todo correcto, saludos!
-Learn as if you were to live forever, live as if you were to die tomorrow-

http://www.mazard.info
http://twitter.com/MazarD
irc://irc.freenode.org/elhacker.net

^kazike^

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

:-[

MazarD

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!
-Learn as if you were to live forever, live as if you were to die tomorrow-

http://www.mazard.info
http://twitter.com/MazarD
irc://irc.freenode.org/elhacker.net

^kazike^

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

MazarD

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#

Código (csharp) [Seleccionar]

[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());
}

-Learn as if you were to live forever, live as if you were to die tomorrow-

http://www.mazard.info
http://twitter.com/MazarD
irc://irc.freenode.org/elhacker.net

^kazike^

perfecto.
muchas gracias xla ayuda!!  :D