Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: ^kazike^ en 9 Septiembre 2009, 18:03 pm



Título: importar dll de c++ en c#
Publicado por: ^kazike^ en 9 Septiembre 2009, 18:03 pm
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:
Citar
No 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
Código:
#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
Código:
#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
Código:
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


Título: Re: importar dll de c++ en c#
Publicado por: MazarD en 9 Septiembre 2009, 18:19 pm
Te falta el .def
Sería algo como:

DLL_lib.def
Código
  1. LIBRARY DLL_lib
  2. EXPORTS
  3. CDLL_lib
  4. getA
  5. getB
  6. etc
  7.  
[/pre]

Por lo demás parece todo correcto, saludos!


Título: Re: importar dll de c++ en c#
Publicado por: ^kazike^ en 9 Septiembre 2009, 18:59 pm
mmm he probado a hacer lo dices, MazarD y me tira:
Citar
error 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
Código:
LIBRARY	DLL_lib
EXPORTS
 CDLL_lib
 getA
 getB
 setA
 setB
 multiplica
 suma
:-[


Título: Re: importar dll de c++ en c#
Publicado por: MazarD en 9 Septiembre 2009, 21:01 pm
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!


Título: Re: importar dll de c++ en c#
Publicado por: ^kazike^ en 10 Septiembre 2009, 09:13 am
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


Título: Re: importar dll de c++ en c#
Publicado por: MazarD en 10 Septiembre 2009, 13:06 pm
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:

Código
  1. LIBRARY prova
  2. EXPORTS
  3. getA
  4. getB
  5. setA
  6. setB
  7. multiplica
  8. suma
  9. nDLL_lib
  10. fnDLL_lib

Código
  1. #define DLL_LIB_EXPORTS
  2. #ifdef DLL_LIB_EXPORTS
  3. #define DLL_LIB_API __declspec(dllexport)
  4. #else
  5. #define DLL_LIB_API __declspec(dllimport)
  6. #endif
  7.  
  8. DLL_LIB_API double multiplica();
  9. DLL_LIB_API int getA();
  10. DLL_LIB_API int getB();
  11. DLL_LIB_API void setA(int a);
  12. DLL_LIB_API void setB(int b);
  13. DLL_LIB_API int suma(void);
  14.  
  15. DLL_LIB_API int nDLL_lib=0;
  16. DLL_LIB_API int fnDLL_lib(void);
  17.  
  18.  


Código
  1. #include "stdafx.h"
  2. #include "prova.h"
  3.  
  4. int a;
  5. int b;
  6.  
  7. #ifdef _MANAGED
  8. #pragma managed(push, off)
  9. #endif
  10.  
  11. BOOL APIENTRY DllMain( HMODULE hModule,
  12. DWORD ul_reason_for_call,
  13. LPVOID lpReserved
  14. )
  15. {
  16. switch (ul_reason_for_call)
  17. {
  18. case DLL_PROCESS_ATTACH:
  19. a=0;
  20. b=0;
  21. case DLL_THREAD_ATTACH:
  22. case DLL_THREAD_DETACH:
  23. case DLL_PROCESS_DETACH:
  24. break;
  25. }
  26. return TRUE;
  27. }
  28.  
  29. #ifdef _MANAGED
  30. #pragma managed(pop)
  31. #endif
  32.  
  33.  
  34. // Ejemplo de función exportada.
  35. DLL_LIB_API int fnDLL_lib(void)
  36. {
  37. return 42;
  38. }
  39.  
  40. int suma(void)
  41. {
  42. return 5+5;
  43. }
  44.  
  45. int getA()
  46. {
  47. return a;
  48. }
  49.  
  50. int getB()
  51. {
  52. return b;
  53. }
  54.  
  55. void setA(int pa)
  56. {
  57. a = pa;
  58. }
  59.  
  60. void setB(int pb)
  61. {
  62. b = pb;
  63. }
  64.  
  65. double multiplica()
  66. {
  67. return (double)a*b;
  68. }


WindowsApplication1 c#

Código
  1. [STAThread]
  2. [DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
  3. public static extern int suma();
  4. [DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
  5. public static extern void setA(int a);
  6. [DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
  7. public static extern void setB(int b);
  8. [DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
  9. public static extern double multiplica();
  10. [DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
  11. public static extern int getA();
  12. [DllImport("C:\\Documents and Settings\\lab\\Escritorio\\dispatch\\prova\\debug\\prova.dll")]
  13. public static extern int getB();
  14.  
  15. private void button1_Click(object sender, EventArgs e)
  16. {
  17. MessageBox.Show(suma().ToString());
  18. setA(11);
  19. setB(11);
  20. MessageBox.Show(multiplica().ToString());
  21. MessageBox.Show(getA().ToString());
  22. MessageBox.Show(getB().ToString());
  23. }


Título: Re: importar dll de c++ en c#
Publicado por: ^kazike^ en 10 Septiembre 2009, 13:37 pm
perfecto.
muchas gracias xla ayuda!!  :D