2010-03-05 10 views
11

Tengo un archivo .lib con su archivo de encabezado (.h). Este archivo tiene algunas funciones que deben usarse en la aplicación C#.Convirtiendo biblioteca de enlaces estáticos a dll dinámico

Después de googlear descubrí que necesito crear una DLL dinámica desde esta biblioteca estática y llamar a esta DLL dinámica desde el código C# utilizando interoperabilidad.

  1. He creado un proyecto win32 y he seleccionado un tipo de DLL.
  2. Archivo de cabecera incluido y .lib agregado a dependencias adicionales.

    Puedo ver las funciones definidas en la biblioteca estática (cuando presiono ctrl + espacio).

Como un novato total no sé cómo puedo exportar la función, que es, en lib con el siguiente firma:

void testfun(char* inp_buff, unsigned short* inp_len, char* buffer_decomp,unsigned *output_len,unsigned short *errorCode) 

Quiero misma firma en mi DLL dinámico con una diferente nombre.

¿Qué escribir en el archivo de encabezado y en el archivo .cpp?

+0

¿Desea un nombre diferente para las funciones exportadas? o nombre diferente para el archivo .dll? –

Respuesta

6

Si puede recompilar su lib, simplemente agregue __declspec(dllexport) a las firmas de todas las funciones que desea exportar.

void __declspec(dllexport) testfun(char* inp_buff, unsigned short* inp_len, char* buffer_decomp,unsigned *output_len,unsigned short *errorCode) 

Si no puede hacer eso, puede exportarlos escribiendo en su lugar un archivo .def. Usando archivos de definición puede incluso cambiar el nombre de una función a medida que se exporta. http://msdn.microsoft.com/en-us/library/28d6s79h.aspx

---- ---- contenido de mylib.def

LIBRARY 

EXPORTS 
    testfun 
    newname=testfun2 

A continuación, cuando se vincula la DLL, incluyen mylib.def

link /dll /machine:x86 /def:mylib.def mylib.lib 

Edit2:

tenga en cuenta que pinvoke asume que las funciones que importa tendrán una convención de llamadas _stdcall a menos que usted indique lo contrario. Por lo tanto, es posible que deba hacer esto también en su código C#.

[DllImport("mylib.dll", CallingConvention=CallingConvention.Cdecl)] 

O bien, puede cambiar su código C++ para ser __stdcall

void __declspec(dllexport) __stdcall testfun(char* inp_buff, ... 
+0

He creado el dll. pero cuando lo llamo desde C#, dijo "No se puede encontrar un punto de entrada llamado 'testfun2' en DLL 'demo.dll'" Cuando veo la lista de funciones exportadas usando DLL export Viewer Muestra el nombre de la función como "? testfun2 @@ YAXPADPAG0PAI @ Z" ¿Cuál sería el problema? – Manjoor

+0

@Manjoor: podría ser. usaste un archivo def o _declspec? Si usó _declspec, entonces probablemente solo necesite corregir sus declaraciones de C# dllImport. Sería útil ver algún código. –

+0

He agregado el código original. por favor, eche un vistazo – Manjoor

3

Cree un nuevo proyecto Dll usando el Asistente para aplicaciones de Visual Studio, y marque "Exportar símbolos" en uno de los pasos del asistente. Crea Dll de muestra que exporta clase, función y variable. Puedes aprender de esta muestra, cómo hacer esto. Generalmente, cada función exportada se declara como __declspec (dllexport). En un proyecto de cliente, se declara como __declspec (dllimport). El código Dll usa la constante que está contaminada como __declspec (dllexport) dentro del proyecto Dll, y __declspec (dllimport) en cualquier otro lugar.

3

Esto es lo que puede hacer

  1. Agregue el código siguiente para que .H archivo.cambiar el nombre de "MYPROJECT" al nombre del proyecto

    #ifdef MYPROJECT_EXPORTS 
    #define MYPROJECT_API __declspec(dllexport) 
    #else 
    #define MYPROJECT_API _declspec(dllimport) 
    #endif 
    
  2. Ir a propiedades-> C++ -> preprocesador y añadir la Defenition - MYPROJECT_EXPORTS

  3. Añadir MYPROJECT_API a todas las funciones que desee el archivo DLL para exponer por ejemplo:

    MYPROJECT_API void Test(); 
    
  4. Ir al proyecto propiedades general -> cambio de tipo de configuración que dll dinámica

Has terminado

+0

Lo he hecho como ustedes me dijeron que hiciera. dll creado. pero no puedo llamarlo desde mi aplicación C#. ver el comentario anterior publicado por mí. – Manjoor

+0

Hola ... el nombre de la función que ves es extraño debido a que C++ name mangling intenta poner: extern "C" en frente de tu función y recompila – SysAdmin

+0

como dijiste he agregado extern "C" before function en mi archivo de cabecera. pero sin suerte (Vea el código a continuación) – Manjoor

3

El dll objetivo, estoy escribiendo, es un contenedor para la biblioteca popular de lzo. He creado el proyecto con el nombre LZO.

Aquí cómo se ve en mi aplicación real.

LZO.h

#ifdef LZO_EXPORTS 
    #define LZO_API __declspec(dllexport) 
    #else 
    #define LZO_API __declspec(dllimport) 
    #endif 

    extern "C" LZO_API void Decompress(char* inp_buff, 
unsigned short* inp_len, char* buffer_decomp,unsigned *output_len); 

LZO.cpp

 #include "stdafx.h" 
     #include "LZO.h" 
     #include "lzo1z.h" 
     #include "lzoconf.h" 
     #include "lz_decomp.c" 

     LZO_API void Decompress(char* inp_buff, unsigned short* inp_len, char* 
    buffer_decomp,unsigned *output_len) 
     { 
      //Calling from static library 
      lzo_decomp (inp_buff,inp_len,buffer_decomp,output_len,NULL); 
     } 

Y finaly mi código C#

//P/Invoke declaration 
[DllImport("LZO.dll")] 
private static extern void Decompress(
    byte[] inp_buff, 
    int inp_len, 
    byte[] buffer_decomp, 
    ref int output_len 
);   

//And calling it as below 
Decompress(src, src.Length, dst, ref outlen); 
// src is byte [] 
// dst is also a byte [] 
// oulen is int 

¿dónde estoy?

+0

hay un error de ortografía "Decoompress" en .H y "Descomprimir" es .Cpp – SysAdmin

+0

Lo he corregido (vea el código editado) pero el problema todavía está allí. – Manjoor

+0

He invocado algunas cosas para probar mi respuesta original –

1

hay dos versiones de LIB se pueden generar, el puño es la lib dinámico, (archivo de origen + cabecera + lib dinámico) -> para acceder a la DLL

o estática lib = (lib dinámico + DLL) -> (Archivo de origen + encabezado) -> para acceder a la DLL.

si usted tiene la Lib dinámico> no hay manera de crear la DLL (no se puede obtener algo de la nada), lib dinámica es simplemente una interfaz,

pero si usted tiene la Lib estático, entonces no hay necesita DLL para acceder es funciones.

0

Eche un vistazo a mi respuesta al this question para una posible solución. Casi seguro de que esto funcionará para usted ...

En resumen: active la opción "Usar entradas de dependencia de la biblioteca" en la configuración de su Enlazador. Si se establece en "verdadero", forzará la vinculación de TODOS los símbolos & código declarado en cada LIB especificada como entrada al proyecto.

+0

Si bien esto puede responder teóricamente a la pregunta, [sería preferible] (// meta.stackoverflow.com/q/8259) incluir aquí las partes esenciales de la respuesta y proporcionar el enlace de referencia. –

+0

@AntonK hecho - agregó parte esencial de la respuesta. –

0

El problema aquí no es cómo se decora el código, es el paso adicional de crear una biblioteca estática que contenga todos los puntos de entrada, y tratar de construir el dll a partir de eso.

Si va con el enfoque __delcspec y crea primero la biblioteca estática, intente vincularla cuando construya una DLL, tendrá que resolver el problema de eliminación de código muerto.

Cuando se vincula, los obj srcs se utilizan para encontrar todas las exportaciones decoradas y las dependencias se resuelven, todo lo demás se elimina.Si no tiene DLL src, entonces no hay archivos obj (excepto quizás un dll main), todo el código en la lib que desea exportar será eliminado (independientemente de los atributos).

Por lo tanto, o bien tienen que:

  1. Informe a todo el enlazador de no dañar código no utilizado, lo que probablemente se va a dar un montón de cosas que no desea.
  2. Utilice un archivo def para exponer las exportaciones manualmente
  3. Vincule el dll con los archivos obj utilizados para crear la lib en lugar de vincular directamente a la lib.
  4. O tal vez crear un código ficticio que haga referencia a las funciones que desea exportar de algo que está exportando.