Matheus Miguel Posted May 26, 2020 at 06:47 PM Share Posted May 26, 2020 at 06:47 PM E ai Pessoal! Beleza? Estou trabalhando com simulações no Ansys (AQWA) e estou tendo problemas para compilar uma DLL que exportará funções para a simulação. Estou usando o Visual Studio 2019, com um tamplate Biblioteca de Vínculo Dinâmico (DLL). Sou bem iniciante com este tipo de programação, pelo desculpas caso o erro seja muito tolo Esses são os meus algortimos: //user_force64.cpp #include "user_force.h" #include "pch.h" #include <stdio.h> extern "C" { __declspec(dllexport) void _stdcall USER_FORCE(int* Mode, int I_Control[100], float R_Control[100], int* Nstruc, float* Time, float* TimeStep, int* Stage, float Position[][6], float Velocity[][6], float Cog[][3], float Force[][6], float Addmass[][6][6], int* ErrorFlag) { // // *** Visual C++ Template // ----------------------- // // 1. Uses stdcall calling convention // 2. Routine name MUST be in upper case // 3. All parameters are passed as pointers // // Input Parameter Description: // // Mode int* - 0 = Initialisation. This routine is called once with mode 0 // before the simulation. All parameters are as described // below except for STAGE, which is undefined. FORCES and // ADDMAS are assumed undefined on exit. // IERR if set to > 0 on exit will cause // the simulation to stop. // // 1 = Called during the simulation. FORCE/ADDMAS output expected. // // 99 = Termination. This routine is called once with mode 99 // at the end of the simulation. // // I_Control[100] - User-defined integer control parameters input in .DAT file. // (int*) // // R_Control[100] - User-defined real control parameters input in .DAT file. // (float*) // // Nstruc int* - Number of structures in the the simulation // // Time float* - The current time (see Stage below) // // Timestep float* - The current timestep (DT, see Stage below) // // Stage int* - The stage of the integration scheme. AQWA time integration is // based on a 2-stage predictor corrector method. This routine is // therefore called twice at each timestep, once with STAGE=1 and // once with STAGE=2. On stage 2 the position and velocity are // predictions of the position and velocity at TIME+DT. // e.g. if the initial time is 0.0 and the step 1.0 seconds then // calls are as follows for the 1st 3 integration steps: // // CALL USER_FORCE(.....,TIME=0.0,TIMESTEP=1.0,STAGE=1 ...) // CALL USER_FORCE(.....,TIME=0.0,TIMESTEP=1.0,STAGE=2 ...) // CALL USER_FORCE(.....,TIME=1.0,TIMESTEP=1.0,STAGE=1 ...) // CALL USER_FORCE(.....,TIME=1.0,TIMESTEP=1.0,STAGE=2 ...) // CALL USER_FORCE(.....,TIME=2.0,TIMESTEP=1.0,STAGE=1 ...) // CALL USER_FORCE(.....,TIME=2.0,TIMESTEP=1.0,STAGE=2 ...) // // Cog[Nstruc][3] - Position of the Centre of Gravity in the Definition axes. // // Position[Nstruc][6] - Position of the structure in the FRA - angles in radians // (float*) // // Velocity[Nstruc][6] - Velocity of the structure in the FRA // (float*) angular velocity in rad/s // // // Output Parameter Description: // // Force[Nstruc][6] - Force on the Centre of gravity of the structure. NB: these // (float) forces are applied in the Fixed Reference axis e.g. // the surge(X) force is ALWAYS IN THE SAME DIRECTION i.e. in // the direction of the X fixed reference axis. // // Addmass[Nstruc][6][6] // (float) - Added mass matrix for each structure. As the value of the // acceleration is dependent on FORCES, this matrix may be used // to apply inertia type forces to the structure. This mass // will be added to the total added mass of the structure at each // timestep at each stage. // // Errorflag int* - Error flag. The program will abort at any time if this // error flag is non-zero. The values of the error flag will // be output in the abort message. int i, j; int struc = 1; //------------------------------------------------------------------------ // MODE#0 - Initialise any summing variables/open/create files. // This mode is executed once before the simulation begins. //------------------------------------------------------------------------ if (*Mode == 0) { } //------------------------------------------------------------------------ // MODE#1 - On-going - calculation of forces/mass //------------------------------------------------------------------------ else if (*Mode == 1) { for (struc = 0; struc < *Nstruc; struc++) { for (i = 0; i < 6; i++) { Force[struc][i] = 2 * Velocity[struc][i]; for (j = 0; j < 6; j++) { Addmass[struc][j][i] = 0.0; } } } *ErrorFlag = 0; } //------------------------------------------------------------------------ // MODE#99 - Termination - Output/print any summaries required/Close Files // This mode is executed once at the end of the simulation //------------------------------------------------------------------------ else if (*Mode == 99) { } //------------------------------------------------------------------------ // MODE# ERROR - OUTPUT ERROR MESSAGE //------------------------------------------------------------------------ else { } return; } } -------------------------------------------------------------------- //user_force.h #pragma once extern "C" { __declspec(dllexport) void _stdcall USER_FORCE(int* Mode, int I_Control[100], float R_Control[100], int* Nstruc, float* Time, float* TimeStep, int* Stage, float Position[][6], float Velocity[][6], float Cog[][3], float Force[][6], float Addmass[][6][6], int* ErrorFlag) } -------------------------------------------------------------------------- // dllmain.cpp : Define o ponto de entrada para o aplicativo DLL. #include "pch.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } Depois de usar o comando dumpbin /exports na DLL gerada, esta é a mensagem: Section contains the following exports for user_force64.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 00011046 _USER_FORCE@52 = @ILT+65(_USER_FORCE@52) Summary 1000 .00cfg 1000 .data 1000 .idata 1000 .msvcjmc 2000 .rdata 1000 .reloc 1000 .rsrc 6000 .text 10000 .textbss E quando uso o mesmo comando em uma DLL funcional, este é o output Dump of file user_force64.dll File Type: DLL Section contains the following exports for user_force64.dll 00000000 characteristics 5D3F15AA time date stamp Mon Jul 29 12:50:02 2019 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 00001000 USER_FORCE Summary 1000 .data 1000 .pdata 1000 .rdata 1000 .reloc 1000 .rsrc 1000 .text Aparentemente errei alguma coisa na compilação, o que causou a diferença no nome da função exportada. Link to comment Share on other sites More sharing options...
Administrators Fernando Mercês Posted May 26, 2020 at 10:24 PM Administrators Share Posted May 26, 2020 at 10:24 PM Citar _USER_FORCE@52 = @ILT+65(_USER_FORCE@52) Interessante... eu nunca tinha visto esse padrão de nome. Não me parece o name decoration / mangling normal de C++. E mesmo assim o extern "C" deveria impedir a decoração, claro, já que C não tem sobrecarga de funções. Será que não há uma função com o mesmo nome nessa pch.h? Achei uma discussão longa de um usuário com um problema muito parecido, inclusive ele cita o mesmo padrão de nomes aqui. Bem, eu iria com baby steps, saca? Compila a menor possível, checa os exports e, se tiver tudo certo, vai crescendo o código e checando os exports da DLL compilada, até encontrar o problema. Por exemplo, o código abaixo foi sem problemas aqui: // user_force.h int _stdcall USER_FORCE(int a, int b); BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } // user_force.cpp extern "C" __declspec(dllexport) int _stdcall USER_FORCE(int a, int b) { return a + b; } Compilação: c:\Users\admin\Documents>cl /LD user_force.cpp Microsoft (R) C/C++ Optimizing Compiler Version 15.00.30729.01 for x64 Copyright (C) Microsoft Corporation. All rights reserved. user_force.cpp Microsoft (R) Incremental Linker Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. /out:user_force.dll /dll /implib:user_force.lib user_force.obj Creating library user_force.lib and object user_force.exp Checagem dos exports: c:\Users\admin\Documents>dumpbin /exports user_force.dll Microsoft (R) COFF/PE Dumper Version 9.00.30729.01 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file user_force.dll File Type: DLL Section contains the following exports for user_force.dll 00000000 characteristics 5ECD966F time date stamp Tue May 26 23:21:35 2020 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 00001000 USER_FORCE Summary 3000 .data 1000 .pdata 2000 .rdata 1000 .reloc Daí seria ir acrescentando o código e recompilando toda hora, até achar o problema... Mas pode ser que alguém saiba exatamente o que ocorre aqui e ajude também. Abraço! Link to comment Share on other sites More sharing options...
Matheus Miguel Posted May 28, 2020 at 05:25 PM Author Share Posted May 28, 2020 at 05:25 PM Agradeço sua resposta, Fernando Mercês Fiz exatamente como você fez. Porém a checagem dos exports foi a seguinte: File Type: DLL Section contains the following exports for user_force.dll 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name 1 0 00001000 _USER_FORCE@8 Summary 2000 .data 6000 .rdata 1000 .reloc B000 .text C:\Users\l04392\source\repos\teste\teste> Esqueci de comentar quando criei o post que o manual do ANSYS diz: " On Windows, the name of the .DLL file must be user_force64.dll, and the file must be located in the same directory as the Aqwa executables (typically C:\Program Files\ANSYS Inc\v201\aqwa\bin\winx64)" Então creio que basta compilar e colocar nesta pasta, certo? Mesmo assim, dá "Solver aborted". A simulação simplesmente não roda Fernando Mercês Você poderia me enviar seu projeto do VS? Link to comment Share on other sites More sharing options...
Administrators Fernando Mercês Posted May 28, 2020 at 10:28 PM Administrators Share Posted May 28, 2020 at 10:28 PM Eu nem criei um projeto, @Matheus Miguel. Criei os dois arquivos e compilei com a linha de comando. ? Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.