2009-02-21 9 views
7

He creado un dll C++ que me gustaría llamar desde el código C#. Puedo llamar a una función, pero la otra arroja una excepción cuando el código C# intenta cargar la dll.Exportación de funciones de C++ dll a C# P/Invoke

La cabecera tiene el siguiente aspecto: (¿qué significa foo = foo en el campo de nombre)

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

Esto produce una DLL con mesa de exportaciones ligeramente confuso:

File Type: DLL 

Section contains the following exports for PPPManager.dll 

00000000 characteristics 
499F44F0 time date stamp Fri Feb 20 16:04:00 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000078E4 Install = Install 
     2 1 000079DC PPPConnect = PPPConnect 

Mi P/Las declaraciones de invocación tienen este aspecto:

[DllImport("PPPManager.dll")] 
private static extern bool Install(); 

[DllImport("PPPManager.dll")] 
private static extern bool PPPConnect(); 

La llamada para instalar devuelve sin excepción, pero cuando llamo a PPPConnec t, obtengo una MissingMethodException - "No se puede encontrar un punto de entrada 'PPPConnect' en una DLL de PInvoke 'PPPManager.dll'."

He intentado eliminar las directivas extern y declspec de la declaración de la función de instalación, de modo que PPPConnect es la única función exportada, y esto todavía no me permite llamar a PPPConnect.

También he intentado hacer el DllImport por ordinal; esto da el mismo resultado que llamar por nombre - Instalar devoluciones, pero PPPConnect arroja la excepción "No se puede encontrar un Punto de entrada '# 2' ...".

El registro de interoperabilidad da:

[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::Install(); 
BOOLEAN (I1_WINBOOL_VAL) Install(); 

JIT ERROR FOR PINVOKE METHOD (Managed -> Native): 
[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::PPPConnect(); 
BOOLEAN (I1_WINBOOL_VAL) PPPConnect(); 

Esto es bien fuera de mi área de especialización, por lo que cualquier sugerencia o pensamientos sería bienvenido.

Gracias, Paul

edición: Resulta que este código hace el trabajo; el problema era que la última dll no se propagaba al dispositivo. D'oh!

+0

nunca he oído hablar de este registro de interoperabilidad - ¿cómo se puede activar/opinión de que? – Charlie

+0

http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx Empecé a usarlo para intentar solucionar este problema, pero parece que me hubiera ahorrado un montón de tiempo de depuración MissingMethodExceptions. – Symmetric

Respuesta

8

¿Está utilizando un archivo .def en su proyecto dll para exportar esas funciones? Si es así, quítalo e intenta de nuevo. Esto es sólo una suposición porque parece que tus exportaciones no son lo que deberían ser cuando haces una declspec "C" externa (dllexports).

He intentado esto con un simple DLL C++ utilizando

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

y una sencilla aplicación C# usando sus declaraciones PInvoke y funcionó bien.

Cuando hice un dumpbin/exportaciones en el DLL que vi:

volcado de archivo PPPManager.dll

Tipo de archivo: DLL

sección contiene los siguientes exportaciones de PPPManager.dll

00000000 characteristics 
499F6C2D time date stamp Fri Feb 20 20:51:25 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000110CD Install = @ILT+200(_Install) 
     2 1 00011069 PPPConnect = @ILT+100(_PPPConnect) 

Observe que los nombres exportados son diferentes en mi caso.

+0

Al final resulta que no estaba copiando el último dll, debido a mi error de comprensión de lo que hace el comando 'Agregar archivo al proyecto' en VS. Tu idea de probar un dll desmontado fue la semilla que necesitaba ir y descubrirlo. ¡Gracias! – Symmetric

+0

¡Genial! Me alegro de poder ayudar. –

0

Gran información, pero como usted menciona, todo está en orden aquí. Intente instalar herramientas de depuración para Windows y ejecute:

kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*" 

para obtener un mejor volcado de la tabla de símbolos; se trata de un golpe ciego también, pero también se podría tratar:

extern "C" 
{ 
    __declspec(dllexport) BOOL Install(); 
    __declspec(dllexport) BOOL PPPConnect(); 
}; 

en caso de que el __declspec está haciendo algo raro.

1

Podría ser algo tan simple como PPPConnect fallar de una manera que sea malinterpretada por el sistema operativo. Intente implementar Install y PPPConnect como no operativas (solo haga que devuelvan TRUE sin hacer nada más) y vea si el error persiste. Si es así, intente intercambiar el orden en el que se exportan (aún como no operativas) y vea si el problema está relacionado con el orden (improbable) o con algo más.

También puede usar la herramienta gráfica depends para confirmar cómo se ve la tabla de exportación de la DLL, pero dudo que el problema provenga de esos sectores.

+0

Estas son buenas ideas para aislar el problema real. También podría intentar agregar una tercera función y ver qué pasa con esa. – Charlie

1

De acuerdo con su descripción Instalar y PPPConnect difiere solo en los nombres. Supongo que simplemente usas la vieja versión .dll con tu aplicación C#. Una sin PPPConnect definido.

Las declaraciones se ven bien (por lo que puedo juzgar sin fuentes).

0

uso Dependency Walker y abrir el archivo DLL para verificar qué métodos están disponibles