16
@_jdepaz José de Paz [email protected] Tutorial Consumir desde C# DLL desarrollada en C++ Ingredientes: -Visual Studio Express 2013 for Windows Desktop -Dependency Walker -Conocimientos de C y C++ (un poco más de lo básico) -Autodidacta ¿Por qué? Porque si no disponemos de una aplicación para ofuscar el código fuente en C# o bien para ofuscar las librerías creadas en C#, entonces la solución viable sería construir una librería en C++, porque hasta el momento no conozco una aplicación para descompilar librerías desarrolladas en C++ y que te devuelve el código fuente. Todos sabemos (bueno eso creo…) que existen aplicaciones para descompilar código C#, de las cuales puedo mencionar “ILSpy” http://ilspy.net/ , de la cual me he favorecido muchas veces. Hay aplicaciones de pago para ofuscar código C# muy buenas, como por ejemplo: Crypto Obfuscator For .NET http://www.ssware.com/cryptoobfuscator/obfuscator-net.htm de la cual también puedo decir que, saca la tarea para lo que se necesita. Por último: Lo nativo (Win32) siempre será mejor que lo interpretado.

Tutorial consumir DLL C++ en C#

Embed Size (px)

DESCRIPTION

Claro que si, como su título lo indica, la raíz de este tutorial es porque hay muy poca información en español sobre como realizar este tipo de tareas. Entonces, me veo en la necesidad de hacer algo útil y que sirva para aquellos que no dejamos de utilizar el lenguaje C/C++ para nuestras tareas rutinarias.

Citation preview

Page 1: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Tutorial Consumir desde C# DLL desarrollada en C++

Ingredientes:

-Visual Studio Express 2013 for Windows Desktop -Dependency Walker -Conocimientos de C y C++ (un poco más de lo básico) -Autodidacta

¿Por qué?

Porque si no disponemos de una aplicación para ofuscar el código fuente en C# o bien para ofuscar las librerías creadas en C#, entonces la solución viable sería construir una librería en C++, porque hasta el momento no conozco una aplicación para descompilar librerías desarrolladas en C++ y que te devuelve el código fuente.

Todos sabemos (bueno eso creo…) que existen aplicaciones para descompilar código C#, de las cuales puedo mencionar “ILSpy” http://ilspy.net/, de la cual me he favorecido muchas veces.

Hay aplicaciones de pago para ofuscar código C# muy buenas, como por ejemplo:

Crypto Obfuscator For .NET

http://www.ssware.com/cryptoobfuscator/obfuscator-net.htm

de la cual también puedo decir que, saca la tarea para lo que se necesita.

Por último: Lo nativo (Win32) siempre será mejor que lo interpretado.

Page 2: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Pasos:

1. Crear solución en Visual Studio Express 2013 de tipo C++ New ProjectVisual C++Win32 Project: Para este ejemplo, el proyecto tendrá el nombre “MyDll” Luego:

En el asistente “Win32 Application Wizard”: Next En “Application type” seleccionar “DLL” Por ultimo “Finish”.

2. La DLL devolverá de C++ a C# los siguientes tipos de datos:

C++ C# LPTSTR string char * string int int double double LPSTR string const char * IntPtr

Así mismo se devolverá una estructura que contiene todos los tipos de datos de la tabla anterior.

Page 3: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

3. Crear las funciones de retorno de valores: Para realizar este paso, es necesario agregar un archivo de encabezado (header), el cual se llamará “MyDll.h”, entonces, seleccionar el proyecto de la solución y proceder a agregar un nuevo ítem, el cual será de tipo “Header File (.h)”. En este archivo se incluirá el encabezado “#include <windows.h>” y se agregarán las definiciones para la exportación de funciones, es decir el archivo “MyDll.h” deberá quedar así (por el momento):

Page 4: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

4. Definir las funciones de exportación: Las funciones a exportar serás las siguientes:

LPTSTR ExportaLptstr() char * ExportaCharA() int ExportaInt() double ExportaDouble() LPSTR ExportaLpstr() const char * ExportaConstChar() BOOL ExportaEstructura(MiEstructura *miEstructura)

En el archivo “MyDll.h” las funciones de exportación quedarán así:

Page 5: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Si realizamos una compilación (Rebuild) previa del proyecto (Ctrl+Alt+F7), la misma se debe realizar sin ningún problema (al menos eso espero):

5. Implementar las funciones en el archivo “MyDll.cpp”

Las funciones deben ser implementadas y por supuesto tienen que devolver el tipo de valor según la definición. Si alguien se pregunta el por qué se está utilizando -extern “C”- en cada función y se supone que es una DLL en C++, al terminar este proceso encontrarán la respuesta. A continuación la implementación de cada función:

Page 6: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Page 7: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

6. Compilar Nuevamente compilar el proyecto, y sin esperar, no tiene ningún motivo para darnos algún error:

7. Configuración de compilación en “MyDll.dll” Si, resulta que: cuando se invoca la función en C#:

Page 8: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

La aplicación termina con código de error, entonces para que esto no suceda, es necesario establecer una propiedad en la compilación de la DLL:

La configuración se realiza accediendo a las propiedades del proyecto (ya saben, haciendo clic con el botón derecho, etc., etc.)

8. Comprobar MyDll.dll con “Dependency Walker” Hay una aplicación llamada “Dependency Walker”, si bien su nombre lo expresa muy bien para que nos sirve, en este caso nos servirá para verificar las funciones que tiene expuestas la DLL que acabamos de compilar. Esta aplicación la pueden encontrar y descargar utilizando el buscador de su preferencia.

Page 9: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Entonces, utilizando “Dependency Walker”; busca la carpeta de depuración en donde encontrarás el archivo “MyDll.dll”, procedemos a abrir la aplicación “Dependency Walker” y luego a cargar la DLL, entonces se mostrarán las funciones expuestas:

9. Crear proyecto en C# En la misma solución, vamos a agregar un nuevo proyecto, en este caso un proyecto C# de consola, el cual se llamara “TestMyDll” (es una sugerencia, porque puede ser a como bien te guste):

Page 10: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

10. Importar funciones de la DLL “MyDll.dll” Bien, ahora en la aplicación de consola vamos a proceder a importar las funciones que nos provee la DLL. NOTA: La DLL “MyDll.dll” tiene que estar presente en la ruta donde se encuentra el ejecutable de la aplicación de consola, en este caso como estamos en modo depuración, se tiene que copiar la DLL en la carpeta “Debug” o bien “Release” si así fuera, por ejemplo:

Page 11: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Seguimos, en “Program.cs” (que es donde está definida la función principal; o sea “Main”) vamos a escribir un poco de código en donde se declaran las funciones que exporta la DLL “MyDll.dll”, y más o menos nos debe quedar así:

Page 12: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Si compilamos y ejecutamos, posiblemente no veamos la salida, entonces tendríamos que poner un punto de interrupción y efectivamente veremos el resultado que nos devuelve la función:

Procedamos a realizar el respectivo análisis:

La función de la DLL en C++ está definida así:

Esto quiere decir: cuando una función que devuelva un tipo de dato “char *”, en C# se debe recibir como “IntPtr” y luego utilizar

Page 13: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

la función Marshal.PtrToStringAnsi para convertir el valor del puntero a “string” respectivamente. Esta fue la primera toma de contacto, ahora resta declarar las demás funciones:

Y como verán, en las funciones que devuelven “LPTSTR” y “LPSTR” también se declaran los valores de retorno como “IntPtr”. Analizando un poco: las funciones que devuelven “cadenas de caracteres” se declaran como “IntPtr” y luego se utiliza la función la función Marshal.PtrToStringAnsi respectivamente.

Page 14: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Ahora, se invocan (o se llaman) las funciones para su respectivo uso:

Y por supuesto, seguido realizamos la compilación y ejecución en modo “Debug”, y ponemos un punto de interrupción en el “return” y sólo resta ver los resultados que tienen las variables: _recibeCharA, _recibeConstChar, _recibeDouble, _recibeInt, _recibeLpStr y _recibeLptStr:

Page 15: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

Con zoom:

Page 16: Tutorial consumir DLL C++ en C#

@_jdepaz José de Paz [email protected]

11. Función que devuelve una estructura Queda pendiente para una próxima entrega…