Programación General > Visual C++
C++ Con Dll De Fortran
Eternal Idol:
Es simple hasta cierto punto, fijate los ret, aunque al no estar completa no puedo estar 100% seguro. En este caso esta claro que las funciones de la DLL de Fortran estan usando stdcall (las que se ven al menos) y por lo tanto cuando tu ejecutable intente acomodar la pila en realidad la jodera ...
En tu ejecutable, convencion de llamada C:
//primero se pasan todos los parametros en la pila
//se llama a la funcion (se que es esta por la cantidad ENORME - por eso decia que ese prototipo era vomitivo - de parametros)
100010A6: E8 29 60 00 00 call 100070D4
//intenta arreglar la pila pero como no es una funcion de convencion C la termina jodiendo
100010AB: 83 C4 38 add esp,38h (56/4=14 parametros)
Para comprobar esta teoria podrias hacer esto en la siguiente linea justo tras llamar esta funcion:
--- Código: Text --- __asm sub esp, 0x38
Si eso lo soluciona evidentemente NO es la forma de hacerlo y tendrias que pedirle mas explicaciones a tu amigo (si esta usando un .DEF, si puede cambiar la convencion de llamada, como esta enlazando, etc, etc, etc) o usar enlazado dinamico :kicking: De esta manera:
typedef void (__stdcall *tuwhbv_ptr)(long,float&,float&,float&,float&,float&,float&,float&,float&,long,float&,float&,float&,float&);
tuwhbv_ptr tuwhbv = 0;
Despues en donde inicies usas LoadLibrary para cargar la DLL en cuestion y GetProcAddress para obtener la direccion de la funcion que se la asignaras a tuwhbv. De esa manera al usar stdcall no deberia dar ningun fallo.
LauraDiaz:
Pues he puesta la linea esta de ensamblador delante de la llamada a la función externa y obtengo el mismo error. He optado por probar el enlace dinámico y en lugar de enlazar el .lib, llamar directamente a la DLL como me has comentado.
Al hacer esto, y generando mi DLL en C++, la llamo desde mi código de Java y sigo teniendo el ACCESS VIOLATION, el cambio es que el "Problematic Frame" que me da el error cambia: usando el enlace estático el problema de java apunta a la DLL que genero en C++, y usando el enlace dinámico el error de la VM me apunta como problema a la DLL de fortran.
La persona que ha hecho el código fortran es un hidrólogo sin muchos conocimientos informaticos y me ha pasado el log que le genera su entorno visual cuando genera la DLL.
--- Código: Text --- # Microsoft Developer Studio Generated NMAKE File, Based on tuwhbv.dsp!IF "$(CFG)" == ""CFG=tuwhbv - Win32 Debug!MESSAGE No configuration specified. Defaulting to tuwhbv - Win32 Debug.!ENDIF !IF "$(CFG)" != "tuwhbv - Win32 Release" && "$(CFG)" != "tuwhbv - Win32 Debug"!MESSAGE Invalid configuration "$(CFG)" specified.!MESSAGE You can specify a configuration when running NMAKE!MESSAGE by defining the macro CFG on the command line. For example:!MESSAGE !MESSAGE NMAKE /f "tuwhbv.mak" CFG="tuwhbv - Win32 Debug"!MESSAGE !MESSAGE Possible choices for configuration are:!MESSAGE !MESSAGE "tuwhbv - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")!MESSAGE "tuwhbv - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")!MESSAGE !ERROR An invalid configuration is specified.!ENDIF !IF "$(OS)" == "Windows_NT"NULL=!ELSE NULL=nul!ENDIF !IF "$(CFG)" == "tuwhbv - Win32 Release" OUTDIR=.\ReleaseINTDIR=.\Release# Begin Custom MacrosOutDir=.\Release# End Custom Macros ALL : "$(OUTDIR)\tuwhbv.dll" CLEAN : -@erase "$(INTDIR)\BETAFUNC.mod" -@erase "$(INTDIR)\betafunc.obj" -@erase "$(INTDIR)\datetrans.mod" -@erase "$(INTDIR)\datetrans.obj" -@erase "$(INTDIR)\hbvmodel.mod" -@erase "$(INTDIR)\hbvmodel.obj" -@erase "$(INTDIR)\Parameters.mod" -@erase "$(INTDIR)\parameters.obj" -@erase "$(INTDIR)\SCECALIB.mod" -@erase "$(INTDIR)\scecalib.obj" -@erase "$(INTDIR)\tuwhbv.obj" -@erase "$(OUTDIR)\tuwhbv.dll" -@erase "$(OUTDIR)\tuwhbv.exp" -@erase "$(OUTDIR)\tuwhbv.lib" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" F90=df.exeF90_PROJ=/compile_only /dbglibs /dll /nologo /warn:nofileopt /module:"Release/" /object:"Release/" F90_OBJS=.\Release/ .SUFFIXES: .fpp .for{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< .f{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< .f90{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< .fpp{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< CPP=cl.exeCPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fp"$(INTDIR)\tuwhbv.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << MTL=midl.exeMTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 RSC=rc.exeBSC32=bscmake.exeBSC32_FLAGS=/nologo /o"$(OUTDIR)\tuwhbv.bsc" BSC32_SBRS= \ LINK32=link.exeLINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\tuwhbv.pdb" /machine:I386 /out:"$(OUTDIR)\tuwhbv.dll" /implib:"$(OUTDIR)\tuwhbv.lib" LINK32_OBJS= \ "$(INTDIR)\betafunc.obj" \ "$(INTDIR)\datetrans.obj" \ "$(INTDIR)\hbvmodel.obj" \ "$(INTDIR)\parameters.obj" \ "$(INTDIR)\scecalib.obj" \ "$(INTDIR)\tuwhbv.obj" "$(OUTDIR)\tuwhbv.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS)<< !ELSEIF "$(CFG)" == "tuwhbv - Win32 Debug" OUTDIR=.\DebugINTDIR=.\Debug# Begin Custom MacrosOutDir=.\Debug# End Custom Macros ALL : "$(OUTDIR)\tuwhbv.dll" CLEAN : -@erase "$(INTDIR)\BETAFUNC.mod" -@erase "$(INTDIR)\betafunc.obj" -@erase "$(INTDIR)\datetrans.mod" -@erase "$(INTDIR)\datetrans.obj" -@erase "$(INTDIR)\DF60.PDB" -@erase "$(INTDIR)\hbvmodel.mod" -@erase "$(INTDIR)\hbvmodel.obj" -@erase "$(INTDIR)\Parameters.mod" -@erase "$(INTDIR)\parameters.obj" -@erase "$(INTDIR)\SCECALIB.mod" -@erase "$(INTDIR)\scecalib.obj" -@erase "$(INTDIR)\tuwhbv.obj" -@erase "$(OUTDIR)\tuwhbv.dll" -@erase "$(OUTDIR)\tuwhbv.exp" -@erase "$(OUTDIR)\tuwhbv.lib" -@erase "$(OUTDIR)\tuwhbv.pdb" "$(OUTDIR)" : if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" F90=df.exeF90_PROJ=/check:bounds /compile_only /dbglibs /debug:full /dll /libs:static /nologo /traceback /warn:argument_checking /warn:nofileopt /winapp /module:"Debug/" /object:"Debug/" /pdbfile:"Debug/DF60.PDB" F90_OBJS=.\Debug/ .SUFFIXES: .fpp .for{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< .f{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< .f90{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< .fpp{$(F90_OBJS)}.obj: $(F90) $(F90_PROJ) $< CPP=cl.exeCPP_PROJ=/nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fp"$(INTDIR)\tuwhbv.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c .c{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.obj:: $(CPP) @<< $(CPP_PROJ) $< << .c{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cpp{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << .cxx{$(INTDIR)}.sbr:: $(CPP) @<< $(CPP_PROJ) $< << MTL=midl.exeMTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 RSC=rc.exeBSC32=bscmake.exeBSC32_FLAGS=/nologo /o"$(OUTDIR)\tuwhbv.bsc" BSC32_SBRS= \ LINK32=link.exeLINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\tuwhbv.pdb" /debug /machine:I386 /out:"$(OUTDIR)\tuwhbv.dll" /implib:"$(OUTDIR)\tuwhbv.lib" /pdbtype:sept LINK32_OBJS= \ "$(INTDIR)\betafunc.obj" \ "$(INTDIR)\datetrans.obj" \ "$(INTDIR)\hbvmodel.obj" \ "$(INTDIR)\parameters.obj" \ "$(INTDIR)\scecalib.obj" \ "$(INTDIR)\tuwhbv.obj" "$(OUTDIR)\tuwhbv.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) $(LINK32) @<< $(LINK32_FLAGS) $(LINK32_OBJS)<< !ENDIF !IF "$(NO_EXTERNAL_DEPS)" != "1"!IF EXISTS("tuwhbv.dep")!INCLUDE "tuwhbv.dep"!ELSE !MESSAGE Warning: cannot find "tuwhbv.dep"!ENDIF !ENDIF !IF "$(CFG)" == "tuwhbv - Win32 Release" || "$(CFG)" == "tuwhbv - Win32 Debug"SOURCE=.\betafunc.forF90_MODOUT=\ "BETAFUNC" "$(INTDIR)\betafunc.obj" "$(INTDIR)\BETAFUNC.mod" : $(SOURCE) "$(INTDIR)" $(F90) $(F90_PROJ) $(SOURCE) SOURCE=.\datetrans.forF90_MODOUT=\ "DATETRANS" "$(INTDIR)\datetrans.obj" "$(INTDIR)\datetrans.mod" : $(SOURCE) "$(INTDIR)" $(F90) $(F90_PROJ) $(SOURCE) SOURCE=.\hbvmodel.forF90_MODOUT=\ "HBVMODEL" "$(INTDIR)\hbvmodel.obj" "$(INTDIR)\hbvmodel.mod" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\Parameters.mod" $(F90) $(F90_PROJ) $(SOURCE) SOURCE=.\parameters.f90F90_MODOUT=\ "PARAMETERS" "$(INTDIR)\parameters.obj" "$(INTDIR)\Parameters.mod" : $(SOURCE) "$(INTDIR)" $(F90) $(F90_PROJ) $(SOURCE) SOURCE=.\scecalib.forF90_MODOUT=\ "SCECALIB" "$(INTDIR)\scecalib.obj" "$(INTDIR)\SCECALIB.mod" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\Parameters.mod" "$(INTDIR)\hbvmodel.mod" "$(INTDIR)\BETAFUNC.mod" $(F90) $(F90_PROJ) $(SOURCE) SOURCE=..\tuwhbv.f90 "$(INTDIR)\tuwhbv.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\SCECALIB.mod" "$(INTDIR)\Parameters.mod" "$(INTDIR)\hbvmodel.mod" "$(INTDIR)\datetrans.mod" "$(INTDIR)\BETAFUNC.mod" $(F90) $(F90_PROJ) $(SOURCE) !ENDIF
puedes ver en esto a lo que te refererias de la convencion de llamada? no se bien como continuar?
Crees que seria una buena idea, que el cambie su proyecto para que le genere una libreria estática? de forma que quizas se cambie la forma de llamar a las librerias que utiliza?
He comprobado que las DLL que el utiliza dentro de su DLL estan todas en el path, así que en principio ese no debería ser el problema, verdad?
y gracias por tu tiempo, a este paso te voy a deber unas cervezas! :)
Eternal Idol:
--- Cita de: "LauraDiaz" ---Pues he puesta la linea esta de ensamblador delante de la llamada a la función externa y obtengo el mismo error.
--- Fin de la cita ---
¿Antes o despues lo pusiste? Tiene que ser asi:
--- Código: Text --- tuwhbv(params);__asm sub esp, 0x38
--- Cita de: "LauraDiaz" ---He optado por probar el enlace dinámico y en lugar de enlazar el .lib, llamar directamente a la DLL como me has comentado.
Al hacer esto, y generando mi DLL en C++, la llamo desde mi código de Java y sigo teniendo el ACCESS VIOLATION, el cambio es que el "Problematic Frame" que me da el error cambia: usando el enlace estático el problema de java apunta a la DLL que genero en C++, y usando el enlace dinámico el error de la VM me apunta como problema a la DLL de fortran.
--- Fin de la cita ---
Por favor deja fuera del problema a Java, hace un programa simple que use la DLL de C++ que a su vez usa la DLL de Fortran.
--- Cita de: "LauraDiaz" ---puedes ver en esto a lo que te refererias de la convencion de llamada? no se bien como continuar?
Crees que seria una buena idea, que el cambie su proyecto para que le genere una libreria estática? de forma que quizas se cambie la forma de llamar a las librerias que utiliza?
--- Fin de la cita ---
Si, me imagino que ese es el problema, al menos entre C++ y Fortran. No se si servira que genere una libreria estatica realmente, pueden hacer la prueba pero no lo se.
LauraDiaz:
la línea que me comentaste la he probado delante y detras de la función externa y lo mismo. En cuanto a dejar Java fuera, eso he hecho, es un programa de pocas lineas que simplemente carga la DLL y con eso no hay problema.
Ahora mismo, el programa en C++ ha quedado así:
--- Código: Text --- typedef void (__stdcall *tuwhbv_ptr)(long,float&,float&,float&,float&,float&,float&,float&,float&,long,float&,float&,float&,float&);tuwhbv_ptr tuwhbv = 0; JNIEXPORT void JNICALL Java_edu_uji_aware_hbv_HBVModel_hbv(JNIEnv *env, jobject obj, jlong flag, jfloat ages, jfloat incon, jfloat inputt, jfloat gobs, jfloat modisa, jfloat param, jfloat lb, jfloat ub, jlong calid, jfloat weight, jfloat parfin, jfloat effin, jfloat output){ HINSTANCE hLib; hLib = LoadLibrary("tuwhbv.dll"); if(hLib!=0){ tuwhbv = (void (__stdcall *)(long,float&,float&,float&,float&,float&,float&,float&,float&,long,float&,float&,float&,float&)) GetProcAddress(hLib,"tuwhbv"); tuwhbv(flag, ages, incon,inputt,gobs,modisa,param,lb,ub,calid,weight,parfin,effin,output); } FreeLibrary(hLib);}
y el error sigue siendo el mismo:
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0b186404, pid=3592, tid=2516
#
# Java VM: Java HotSpot Client VM (1.5.0_08-b03 mixed mode)
# Problematic frame:
# C [tuwhbv.dll+0x6404]
las librerias que usa el tuwhbv.dll estan todas disponibles,y abriendolo con el dependency walker todo tiene buena pinta. Alguna idea de como quitarme de encima este access violation?
gracias y un saludo!
Eternal Idol:
Si la parte de Fortran y C++ funciona bien y el problema ahora es con Java yo no te puedo ayudar, no tengo experiencia ni tiempo para conseguirla. Proba a preguntar en el subforo de Java, tal vez ahi alguien sepa.
Navegación
[#] Página Siguiente
[*] Página Anterior
Ir a la versión completa