Ir para conteúdo

Como compilar uma DLL corretamente?


Matheus Miguel

Posts Recomendados

 

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 para o comentário
Compartilhar em outros sites

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 para o comentário
Compartilhar em outros sites

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 para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...