¿Es posible pasar una referencia a un puntero de Excel VBA a C++?

 C Programming >> Programación C >  >> Tags >> Excel
¿Es posible pasar una referencia a un puntero de Excel VBA a C++?


Me gustaría llamar a mi propia función dll de C++ desde excel vba:


void my_cpp_fun ( int& n_size, double*& my_array);

La función de C++ crea una matriz my_array de tamaño variable n_size (este tamaño se calcula dentro de my_cpp_fun).


¿Puedo conectar esta función tal cual a VBA sin usar nada específico de Excel en mi código C++?


Entonces, básicamente, lo que estoy buscando es una declaración de declaración de VBA como


Declare Sub my_cpp_fun Lib "my_cpp.dll" (n_size As Long, Ref_to_Ptr_Qualifier my_array As Double) 

Un problema adicional que se me acaba de ocurrir:si asigno memoria dentro del dll de C++ usando new, ¿estará disponible esa memoria una vez que la función dll devuelva el control a VB? Si ese no es el caso, lo anterior no tiene sentido...


Respuestas:


Respuesta corta:sí, es posible (y más fácil que la ruta COM, en mi opinión) llamar funciones en una DLL desde VBA. En mi experiencia, la mejor manera de hacerlo es escribir funciones de contenedor con C enlace (para evitar encontrarse con varios esquemas de manipulación de nombres de C++) y exponer una interfaz de punteros en lugar de referencias (ya que el tipo de VBA apropiado para declarar un argumento de referencia o resultado será bastante difícil de predecir).


Una gran guía sobre cómo escribir Declare apropiado declaraciones (asumiendo Windows de 32 bits) es el Capítulo 2 del libro "Hardcore Visual Basic", si puede encontrarlo.


Tenga en cuenta también que cualquier función expuesta a VBA a través de Declare las declaraciones deberán usar la convención de llamada stdcall (también conocida como WINAPI).


TLDR:


Yo haría esto:



extern 'C' {
void WINAPI my_cpp_fun_wrapper ( int *n_size, double **my_array )
{
my_cpp_fun(*n_size, *my_array);
}
}

y luego


Declare Sub my_cpp_fun_wrapper Lib "my_cpp.dll" (ptr_n_size As Long, ptr_ptr_my_array As Long)


y usa los distintos *Ptr funciones de VB6/VBA para obtener los punteros a mis datos.


Algunas respuestas de código


#include <windows.h>
__declspec(dllexport) int __stdcall asAny(void* pointer) {
char buf[200];
if (! pointer) {
// return 0 (false) to indicate that pointer was a null pointer
return 0;
}
wsprintfA(buf, "pointer = %p, *pointer = %s", pointer, (wchar_t*) pointer);
MessageBoxA(0, buf, "asAny", 0);
// return -1 (true) to indicate that ptrFoo was not a null pointer
return -1;
}
option explicit  declare ptrSafe function asAny
_
lib "the.dll" ( _ byVal pointer as any _
) as boolean sub main()
if asAny( nothing ) then
debug.print("asAny( nothing )
returned true" )
else
debug.print("asAny( nothing )
returned false")
end if ' -------------------------------------------------------- ' if asAny( 0 ) then -->
Compilie error: Type mismatch ' --------------------------------------------------------
if asAny( vbNullString ) then
debug.print("asAny( vbNullString ) returned true" )
else
debug.print("asAny( vbNullString ) returned false")
end if ' --------------------------------------------------------
dim text as string
text = "Hello World"
if asAny( text ) then
debug.print("asAny( text )
returned true" )
else
debug.print("asAny( text )
returned false")
end if end sub
LIBRARY the EXPORTS   asAny