Alain Thiffault
Alain Thiffault

Reputation: 608

delphi calling AMD ADL c++ dll

Trying to interface with AMD ADL library (DLL) to retrieve info on the graphics card. Got some of the functions to work but having problems.

Pls see this post with same question but no answer: ATI ADL - AdapterInfo_Get

The function returns using a delphi array but the content is wrong.
The function returns using a pointer to a buffer but the data is the same [wrong].
[see below for code example]

The function is defined in the documentation as follows:

int ADL_Adapter_AdapterInfo_Get(LPAdapterInfo   lpInfo,   int  iInputSize)          


Retrieves all OS-known adapter information. 

This function retrieves the adapter information of all OS-known adapters in the
system. OS-known adapters can include adapters that are physically present in the  
system (logical adapters) as well as ones that are no longer present in the system   
but are still recognized by the OS.

Supported Platforms:
Linux and Windows(XP, Vista and Windows 7); 32bit and 64bit 

Parameters:
[in]    iInputSize  The size of the lpInfo buffer. 
[out]   lpInfo  The pointer to the buffer containing the retrieved adapter information. 

Returns:
If the function succeeds, the return value is ADL_OK. Otherwise the return value is an ADL error code. Result Codes

Remarks:
This API take a fixed-size output array. For dynamic-size output, use ADL_Adapter_AdapterInfoX2_Get function. 

The adl_structures.pas file defines AdapterInfo as follows: type

  AdapterInfo = record
    iSize : integer;
    iAdapterIndex : integer;
    strUDID : array [0..ADL_MAX_PATH] of char;
    iBusNumber : integer;
    iDeviceNumber : integer;
    iFunctionNumber : integer;
    iVendorID : integer;
    strAdapterName : array [0..ADL_MAX_PATH] of char;
    strDisplayName : array [0..ADL_MAX_PATH] of char;
    iPresent : integer;

   {$IFDEF MSWINDOWS}
    iExist : Integer;
    strDriverPath : array [0..ADL_MAX_PATH-1] of Char;
    strDriverPathExt : array[0..ADL_MAX_PATH-1] of Char;
    strPNPString : array[0..ADL_MAX_PATH-1] of char;
    iOSDisplayIndex : integer;  
   {$ENDIF} { (_WIN32) || (_WIN64) }

  end;
  LPAdapterInfo = ^AdapterInfo;

I declared a type for each function this way:

type
  TADL_MAIN_CONTROL_CREATE = function(param1 : ADL_MAIN_MALLOC_CALLBACK; param2 : integer) : integer; cdecl;
  TADL_MAIN_CONTROL_DESTROY = function : integer; cdecl;
  TADL_OVERDRIVE5_TEMPERATURE_GET = function (iAdapterIndex, iThermalControllerIndex : integer; var lpTemperature : ADLTemperature) : integer; cdecl;
  TADL_OVERDRIVE5_FANSPEED_GET = function (iAdapterIndex, iThermalControllerIndex: integer; var lpFanSpeedValue: ADLFanSpeedValue): integer; cdecl;
  TADL_ADAPTER_NUMBEROFADAPTERS_GET = function (var lpNumAdapters: integer): integer; cdecl;
  TADL_ADAPTER_ACTIVE_GET = function(iAdapterIndex: integer; var lpStatus: Integer): Integer; cdecl;
  TADL_ADAPTER_ADAPTERINFO_GET = function(AInfo : Pointer; iInputSize: Integer): integer; cdecl;{stdcall;}

Created variables this way:

var
  ADL_Overdrive5_Temperature_Get : TADL_OVERDRIVE5_TEMPERATURE_GET;
  ADL_Adapter_NumberOfAdapters_Get : TADL_ADAPTER_NUMBEROFADAPTERS_GET;
  ADL_Adapter_Active_Get : TADL_ADAPTER_ACTIVE_GET;
  ADL_Adapter_AdapterInfo_Get : TADL_ADAPTER_ADAPTERINFO_GET;
  ADL_Overdrive5_FanSpeed_Get : TADL_OVERDRIVE5_FANSPEED_GET;

  temperature : ADLTemperature;
  fanspeed : ADLFanSpeedValue;
  numGFX, numActiveGFX : Integer;
  GFXActive : Integer;
  x, size : integer;

  ADL_Info : AdapterInfo;
  ADL_PInfo : LPAdapterInfo;

  ADL_AInfo : Array of AdapterInfo;

  ADL_Result : Integer;
  ActiveAdapters : Array of Integer;
  Addr : Pointer;
  strPresent : String;

Linking to external functions this way:

ADL_Adapter_NumberOfAdapters_Get := GetProcAddress(hDLL, 'ADL_Adapter_NumberOfAdapters_Get');
    ADL_Overdrive5_Temperature_Get := GetProcAddress(hDLL, 'ADL_Overdrive5_Temperature_Get');
    ADL_Adapter_Active_Get := GetProcAddress(hDLL, 'ADL_Adapter_Active_Get');
    ADL_Adapter_AdapterInfo_Get := GetProcAddress(hDLL, 'ADL_Adapter_AdapterInfo_Get');
    ADL_Overdrive5_Fanspeed_Get := GetProcAddress(hDLL, 'ADL_Overdrive5_FanSpeed_Get');

I then try to get the data into an array and into a memory buffer. Both return the exact same data but its not valid. Note that the other functions are working or return valid errors such as "not supported by driver".

Array:

if Assigned(ADL_Adapter_AdapterInfo_Get) then
    begin
      //*** Array (delphi way)
      Setlength(ADL_AInfo, numGFX);
      Addr := ADL_AInfo;
      size := sizeof(AdapterInfo)*numGFX;

      try
        ADL_Result := ADL_Adapter_AdapterInfo_Get(Addr, size);
        If ADL_Result = ADL_OK then
        begin
          for x := 0 to numGFX-1 do
            begin
              //using a delphi array
              Memo1.Lines.Add('Vender ID for Adapter Index '+IntToStr(ADL_AInfo[x].iAdapterIndex)+' is '+IntToStr(ADL_AInfo[x].iVendorID));
              Memo1.Lines.Add('Device Number for Adapter Index '+IntToStr(ADL_AInfo[x].iAdapterIndex)+' is '+IntToStr(ADL_AInfo[x].iDeviceNumber));
              Memo1.Lines.Add('Adatper Name for Adapter Index '+IntToStr(ADL_AInfo[x].iAdapterIndex)+' is '+ADL_AInfo[x].strAdapterName);
              Memo1.Lines.Add('Display Name for Adapter Index '+IntToStr(ADL_AInfo[x].iAdapterIndex)+' is '+ADL_aInfo[x].strDisplayName);
              if ADL_AInfo[x].iPresent = 0 then strPresent := 'not present' else strPresent := 'present';
              Memo1.Lines.Add('Adapter Index '+IntToStr(ADL_AInfo[x].iAdapterIndex)+' is '+strPresent);
            end;
        end
        else
          Memo1.Lines.Add('Error : '+IntToStr(ADL_Result));
      finally
      end;
    end;

Memory buffer:

if Assigned(ADL_Adapter_AdapterInfo_Get) then
begin
  //*** Pointer (c lookalike)
  size := sizeof(AdapterInfo)*numGFX;
  //GetMem(ADL_PInfo, size);
  ADL_PInfo := AllocMem(sizeof(AdapterInfo) * numGFX);


  try
    ADL_Result := ADL_Adapter_AdapterInfo_Get(ADL_PInfo, size);
    If ADL_Result = ADL_OK then
    begin
      for x := 0 to numGFX-1 do
        begin
          //using getmem with a pointer to a record
          Memo1.Lines.Add('Vender ID for Adapter Index '+IntToStr(ADL_PInfo.iAdapterIndex)+' is '+IntToStr(ADL_PInfo.iVendorID));
          Memo1.Lines.Add('Device Number for Adapter Index '+IntToStr(ADL_PInfo.iAdapterIndex)+' is '+IntToStr(ADL_PInfo.iDeviceNumber));
          Memo1.Lines.Add('Adatper Name for Adapter Index '+IntToStr(ADL_PInfo.iAdapterIndex)+' is '+ADL_PInfo.strAdapterName);
          Memo1.Lines.Add('Display Name for Adapter Index '+IntToStr(ADL_PInfo.iAdapterIndex)+' is '+ADL_PInfo.strDisplayName);
          if ADL_PInfo.iPresent = 0 then strPresent := 'not present' else strPresent := 'present';
          Memo1.Lines.Add('Adapter Index '+IntToStr(ADL_PInfo.iAdapterIndex)+' is '+strPresent);

          inc(ADL_Pinfo);
        end;
    end
    else
      Memo1.Lines.Add('Error : '+IntToStr(ADL_Result));

  finally

   // ZeroMemory(ADL_PInfo, size);
  end;
end;

Upvotes: 0

Views: 791

Answers (1)

Alain Thiffault
Alain Thiffault

Reputation: 608

Solution is simple.

  1. download the PRAXIS library
  2. look for all instances of Char within the file "adl_structures.pas" and change them to AnsiChar
  3. in the same file, look for all instances of "[0..MAX_PATH]" and change them to "[0..MAX_PATH-1]"

The code above to get the pointers to the functions in the DLL and extract data is valid and works fine

Upvotes: 0

Related Questions