Installation de paquets spécifiques
On va essayer de créer un programme qui n'est pas pour Linux, ni pour Windows, mais pour Wine.
Winegcc, ce n'est pas Wine, et ce n'est pas gcc.
C'est une chaine de compilation spéciale pour wine, qui utilise gcc.
Il faut installer ces deux paquets: le développement de Wine

sudo dnf install wine-devel
et l'extension c++ de gcc
sudo dnf install gcc-c++

Le fichier dll: dll.c
Il contient le code de 3 fonctions:
fun(), qui imprime "Hello from dll!".
calc(), qui calcule a*b.
et GetSystemPowerStatus(), qui contrôle l'état de la batterie.
NtPowerInformation() ne semble pas être une fonction Windows, mais une fonction du noyau, dont le code source se trouve dans dlls/ntdll/unix/system.c de Wine

#include <stdio.h>
#include <stdarg.h>

#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <winternl.h>
#include <wine/debug.h>

void fun(void)
{
  printf("Hello from dll!\n");
}


int calc(int a, int b)
{
  return a*b ;
}


/***********************************************************************
 *           GetSystemPowerStatus      (KERNEL32.@)
 */
BOOL WINAPI GetSystemPowerStatus(LPSYSTEM_POWER_STATUS ps)
{
    SYSTEM_BATTERY_STATE bs;
    NTSTATUS status;

    //TRACE("(%p)\n", ps);

    ps->ACLineStatus        = AC_LINE_UNKNOWN;
    ps->BatteryFlag         = BATTERY_FLAG_UNKNOWN;
    ps->BatteryLifePercent  = BATTERY_PERCENTAGE_UNKNOWN;
    ps->SystemStatusFlag    = 0;
    ps->BatteryLifeTime     = BATTERY_LIFE_UNKNOWN;
    ps->BatteryFullLifeTime = BATTERY_LIFE_UNKNOWN;

    status = NtPowerInformation(SystemBatteryState, NULL, 0, &bs, sizeof(bs));
    if (status == STATUS_NOT_IMPLEMENTED) return TRUE;
    if (FAILED(status)) return FALSE;

    ps->ACLineStatus = bs.AcOnLine;

    if (bs.BatteryPresent)
    {
        ps->BatteryLifePercent = bs.MaxCapacity ? 100 * bs.RemainingCapacity / bs.MaxCapacity : 100;
        ps->BatteryLifeTime = bs.EstimatedTime;
        if (!bs.Charging && (LONG)bs.Rate < 0)
            ps->BatteryFullLifeTime = 3600 * bs.MaxCapacity / -(LONG)bs.Rate;

        ps->BatteryFlag = 0;
        if (bs.Charging)
            ps->BatteryFlag |= BATTERY_FLAG_CHARGING;
        if (ps->BatteryLifePercent > 66)
            ps->BatteryFlag |= BATTERY_FLAG_HIGH;
        if (ps->BatteryLifePercent < 33)
            ps->BatteryFlag |= BATTERY_FLAG_LOW;
        if (ps->BatteryLifePercent < 5)
            ps->BatteryFlag |= BATTERY_FLAG_CRITICAL;
    }
    else
    {
        ps->BatteryFlag = BATTERY_FLAG_NO_BATTERY;
    }

    return TRUE;
}

Le fichier spec: dll.spec

@ cdecl fun()
@ cdecl calc(long long)
@ cdecl GetSystemPowerStatus(ptr)

Le fichier d'appel de la dll: exec.c

#include <stdio.h>
#include <windows.h>

#include <ntstatus.h>
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <winternl.h>

int main()
{
  printf("Hello from exe!\n") ;

  typedef void fptr(void) ;
  typedef int calcptr(int a, int b) ;
  typedef BOOL WINAPI getpwstatusptr(LPSYSTEM_POWER_STATUS ps) ;

  HMODULE lib = LoadLibraryA("dll.dll.so") ;
  if (NULL == lib)
  {
    lib = LoadLibraryA("linuxhost.dll") ;
  }
  if (lib)
  {
    fptr* f = (fptr*)GetProcAddress(lib, "fun") ;
    if (f != NULL)
    {
      f() ;
    }
    else
    {
      printf("No fun found :(\n") ;
    }
    
    calcptr* c = (calcptr*)GetProcAddress(lib, "calc") ;
    if (c != NULL)
    {
       int a = 2, b=3 ;
       
       a = c(a, b) ;
       printf("2*3=%ld\n", a) ;
    }
    
    getpwstatusptr* gps = (getpwstatusptr*)GetProcAddress(lib, "GetSystemPowerStatus") ;
    if (NULL != gps)
    {
      SYSTEM_POWER_STATUS pw, *pwptr ;
      
      pwptr = &pw ;
      
      BOOL toto = gps(&pw) ;
      
      printf("toto = %ld\n", toto) ;
      if (toto)
      {
        // 0=Offline, 1=OnLine else Unknown
        printf("ACLineStatus %ld\n", pwptr->ACLineStatus) ;

        // 1  High, more than 66%
        // 2  Low, less than 33%
        // 4  Critical, less than 5%
        // 8  Charging
        // 128 No Battery
        printf("BatteryFlag  %ld\n", pwptr->BatteryFlag ) ;

        // 255 or percent
        printf("BatteryLifePercent %ld\n", pwptr->BatteryLifePercent) ;

        // 0 Battery saver is off. 
        // 1 Battery saver on. Save energy where possible. 
        printf("SystemStatus %ld\n", pwptr->SystemStatusFlag) ;

        // -1 or something
        printf("BatteryLifeTime %ld\n", pwptr->BatteryLifeTime) ;

        // -1 or something
        printf("BatteryFullLifeTime %ld\n", pwptr->BatteryFullLifeTime) ;

        if (pwptr->ACLineStatus != 255)
        {
          if (pwptr->ACLineStatus == 0) printf("OffLine\n") ;
          if (pwptr->ACLineStatus == 1) printf("OnLine\n") ;
        }

        if (pwptr->BatteryLifePercent != 255)
        {
          printf("%ld %%\n", pwptr->BatteryLifePercent) ;
        }

        if (pwptr->BatteryFlag != 255)
        {
          if (pwptr->BatteryFlag &   1) printf("more than 66%\n") ;
          if (pwptr->BatteryFlag &   2) printf("less than 33%\n") ;
          if (pwptr->BatteryFlag &   4) printf("less than 5%\n") ;
          if (pwptr->BatteryFlag &   8) printf("charging\n") ;
          if (pwptr->BatteryFlag & 128) printf("No battery\n") ;
        }
      }
    }
    
  }
  else
  {
    printf("No library found\n") ;
  }
}

Le fichier makefile

target: dll exec

dll: dll.c dll.spec
	winegcc -shared dll.c dll.spec -o dll

exec : exec.c
	winegcc exec.c -o exec

Le lancement de la compilation
Créer un répertoire n'importe où dans l'espace utilisateur.
Copier les fichiers dll.c, dll.spec, exec.c et makefile.
Se positionner dans le répertoire, très simple, clic droit et "Ouvrir dans un terminal".

Une fois le terminal ouvert, taper make.
La compilation devrait se lancer et se dérouler sans erreur.

Le lancement du programme
Pour lancer le programme, il ne faut pas oublier de dire que l'on veut un programme du répertoire courant, pas un programme du shell.
./exec.exe

Après quelques lignes, nous rappelant que ce que l'on fait est un peu hors norme, on retrouve la sortie de notre programme d'appel à la dll.

Conclusion
Vite, la suite ! On a vu Wine, WinUAE, on va jouer avec les deux...