Llamando a la API de Win32 específico de Delphi - ¿Por qué las excepciones volar sin un “pop asm ...”?

StackOverflow https://stackoverflow.com/questions/1093206

Pregunta

Estoy utilizando Delphi para hacer un XLL de complemento para Excel, que consiste en realizar una gran cantidad de llamadas a la función de xlcall32.dll Excel4v . Sin embargo, como supongo muy pocos expertos Delphi aquí han trabajado con esa API específica, estoy esperando que el problema podría haber sido observado en otras API también.

En C, específicamente en el archivo xlcall.h que viene con el Microsoft Excel 2007 XLL SDK , Excel4v se define como:

int pascal Excel4v(int xlfn, LPXLOPER operRes, int count, LPXLOPER opers[]);

En Delphi que estoy usando:

function Excel4v(xlfn: Integer; operRes: LPXLOPER; count: Integer;
    opers: array of LPXLOPER): Integer; stdcall; external 'xlcall32.dll';

LPXLOPER es un puntero a una estructura (en C) o registro (en Delphi).

He estado haciendo mi tarea en declarar funciones de C en Delphi ( este excelente artículo fue una gran ayuda), y creo que estoy declarando Excel4v correctamente. Sin embargo, las llamadas de código de Delphi en que la función de causa excepciones ( "violación de acceso ..." es lo que sigo viendo) a menos que que son seguidos por la línea siguiente:

asm pop sink; end;

Donde "sumidero" se define en algún lugar como un entero.

No tengo ninguna pista sobre el montaje ... así que no hay manera lo que he pensado para tratar de fijar las excepciones con "sumidero pop asm; end;". Pero "asm fregadero pop; fin;" en efecto fijar las excepciones. Vi por primera vez usado en este artículo útil en la fabricación de XLL usando Delphi . Aquí está la cita más relevante:

  

"A partir de Delphi el gran obstáculo   con complementos es el parámetro extra   después de que la dirección de retorno en la pila.   Esto viene gratis con cada llamada a   Sobresalir. Nunca he encontrado a cabo lo que se   se mantiene, pero siempre y cuando lo tiras   de distancia, el complemento no tendrán ningún problema. Añadir   la variable pop línea asm, final; después   donde cada llamada variable puede ser cualquier   variable global, local o objeto que   es al menos 4 bytes número entero largo es   multa. Para REPEAT- éstos deberán incluirse   después de cada llamada Excel4v. De otra manera   usted está construyendo una bomba de tiempo ".

Quiero entender lo que está sucediendo realmente, y por qué . ¿Qué podría estar causando una función Win32 para devolver un "parámetro extra después de la dirección de retorno en la pila", y qué es lo que realmente significa?

Podría haber otra manera de solucionar este problema, por ejemplo, con una opción de compilador diferente o una forma diferente de la que se declara la función?

Y ¿hay algo arriesgado en llamar "sumidero pop asm; fin;" después de cada llamada a Excel4v ...? Parece que funciona bien, pero, como yo no entiendo lo que está pasando, se siente un poco peligroso ...

¿Fue útil?

Solución

No creo que es Pascal vs stdcall - son convenciones de llamada muy similares y no deben dar lugar a una pila no coincidentes en la salida de función

.

Desde el href="http://rvelthuis.de/articles/articles-convert.html#arrayparams" ,

  

Esto sería de hecho un muy buen   la sintaxis, pero no es el mismo que el   por encima de definición de matriz. Gama de   parámetros son parámetros de matriz abiertos.   Pueden parecer cualquier matriz, y   hacer aceptar cualquier matriz, pero que reciben una   extra (oculto) de parámetros, que posee   el índice más alto de la matriz (la   Alto valor). Puesto que esto es sólo por lo que en   Delphi, y no en C o C ++, que había   tener un verdadero problema. (Véase también mi   artículo sobre antenas abiertas), ya que la   número real de los parámetros no lo haría   partido.

Te estás poniendo el parámetro adicional "más alto índice de matriz" se pasa a la función. Se trata de un int y tiene que ser limpiado cuando la función de salidas para que no terminan con una pila corrompido y accidente. El artículo indica cómo pasar matrices a funciones C.

Algo así como:

type
 PLPXLOPER  = ^LPXLOPER;

Y pasar PLPXLOPER como el último parámetro.

Otros consejos

funciones

La mayoría de Windows usar __stdcall su convenciones de llamada .

Su convención de llamada está mal, en concreto el "stdcall". La declaración C se especifica como "pascal"

STDCALL pasa parámetros en orden de izquierda a derecha, espera que la rutina para limpiar, y no utiliza registros. Pascal, otoh pasa parámetros de izquierda a derecha orden. Por lo tanto, las cosas no están sucediendo la forma en la otra mitad del código de espera en cualquiera de los casos.

Cambiar su declaración Delphi ser también "Pascal" en lugar de "stdcall".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top