Link to home
Start Free TrialLog in
Avatar of viziopoint
viziopoint

asked on

double pointers in c dll

Need some help calling a c dll with Delphi XE2 and I've been stuck on this for a few days now - appreciate some help.

Specifically I am trying to interface with AMD's ADL library to get information on the graphics card installed.

I have many functions working but one in particular calls for a pointer to a pointer (?) to an array.  I read up on this and it seems that this is done regularly when a function call needs to populate an array while at the same time return an success/error code.  I would like to understand how this works.

At this point my code compiles and many of the functions return valid data so I know I have part of it working.  For the call I having problems with, the documentation says:

Function Documentation
int ADL_Display_DisplayInfo_Get       (      int       iAdapterIndex,
            int *       lpNumDisplays,
            ADLDisplayInfo **       lppInfo,
            int       iForceDetect       
      )                  


Function to retrieve the adapter display information.

This function retrieves display information for a specified adapter. Display information includes display index, name, type, and display connection status, etc.
 This API uses the Caller's Memory Allocation Callback Function to allocate memory pointed by lppInfo. Caller is responsible to de-alocate the memory.
Supported Platforms:
Linux and Windows(XP, Vista and Windows 7); 32bit and 64bit
Parameters:[in]       iAdapterIndex       The ADL index handle of the desired adapter. A value of -1 returns all displays in the system across multiple GPUs.
[out]       lpNumDisplays       The pointer to the number of displays detected.
[out]       lppInfo       The pointer to the pointer to the retrieved display information array. Initialize to NULL before calling this API. Refer to the ADLDisplayInfo structure for more information.
[in]       iForceDetect       0: Do not force detection of the adapters in the system; 1 : Force detection

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 uses the memory allocation callback function provided by the user.

I declared it this way:

 
 TADL_DISPLAY_DISPLAYINFO_GET = function(iAdapterIndex: integer; var lpNumDisplays : integer; var AInfo: LPADLDisplayInfo ; iForceDetect: integer): integer; cdecl;

Open in new window


and then call it this way:

if Assigned(ADL_Display_DisplayInfo_Get) then
                  begin
                    lppInfo := nil;
                    ADL_Result := ADL_Display_DisplayInfo_Get(ADL_AInfo[x].iAdapterIndex, NumDisplays, lppInfo,1);
                    if ADL_Result = ADL_OK then
                    begin
                      DisplayInfo := lppInfo^;
                      Memo1.Lines.Add('Display Name: '+lppInfo.strDisplayName);
                      Memo1.Lines.Add('Manufacturer Name: '+lppInfo.strDisplayManufacturerName);
                    end
                    else
                      Memo1.Lines.Add('Error: DisplayInfo :'+String(ADL_ERROR_LOOKUP[ADL_Result]));

                  end;

Open in new window


The call completes and returns ADL_OK but I can't find the data.  I'm thinking that this line is wrong:  

DisplayInfo := lppInfo^;

I can upload my code if it helps.
Avatar of viziopoint
viziopoint

ASKER

I found this from c example:

// Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection

 if (null != ADL.ADL_Display_DisplayInfo_Get)
 {
       IntPtr DisplayBuffer = IntPtr.Zero;
       int j = 0;
                                            
       ADLRet = ADL.ADL_Display_DisplayInfo_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 1);
       if (ADL.ADL_SUCCESS == ADLRet)
      {
             List<ADLDisplayInfo> DisplayInfoData = new List<ADLDisplayInfo>();
             for (j = 0; j < NumberOfDisplays; j++)
             {
                  oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(DisplayBuffer.ToInt32() + j * Marshal.SizeOf(oneDisplayInfo)), oneDisplayInfo.GetType());
                  DisplayInfoData.Add(oneDisplayInfo);
                  }
                 Console.WriteLine("\nTotal Number of Displays supported: " + NumberOfDisplays.ToString());
                 Console.WriteLine("\nDispID  AdpID  Type OutType  CnctType Connected  Mapped  InfoValue DisplayName ");

                for (j = 0; j < NumberOfDisplays; j++)
                {
                      int InfoValue = DisplayInfoData[j].DisplayInfoValue;
                      string StrConnected = (1 == (InfoValue & 1)) ? "Yes" : "No ";
                      string StrMapped = (2 == (InfoValue & 2)) ? "Yes" : "No ";
                      int AdpID = DisplayInfoData[j].DisplayID.DisplayLogicalAdapterIndex;
                      string StrAdpID = (AdpID < 0) ? "--" : AdpID.ToString("d2");

                     Console.WriteLine(DisplayInfoData[j].DisplayID.DisplayLogicalIndex.ToString() + "        " +
                     StrAdpID + "      " +
                     DisplayInfoData[j].DisplayType.ToString() + "      " +
                     DisplayInfoData[j].DisplayOutputType.ToString() + "      " +
                     DisplayInfoData[j].DisplayConnector.ToString() + "        " +
                     StrConnected + "        " +
                     StrMapped + "      " +
                     InfoValue.ToString("x4") + "   " +
                     DisplayInfoData[j].DisplayName.ToString());
                     }
                    Console.WriteLine();
               }
               else
               {
                     Console.WriteLine("ADL_Display_DisplayInfo_Get() returned error code " + ADLRet.ToString());
               }
              // Release the memory for the DisplayInfo structure
             if (IntPtr.Zero != DisplayBuffer)
                 Marshal.FreeCoTaskMem(DisplayBuffer);
    }

Open in new window


Would this mean that I need to declare DisplayBuffer as an IntPtr in Delphi (XE2)?

An how would I translate something like this to Delphi array?

oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(DisplayBuffer.ToInt32() + j * Marshal.SizeOf(oneDisplayInfo)), oneDisplayInfo.GetType());
                  DisplayInfoData.Add(oneDisplayInfo); 

Open in new window

SOLUTION
Avatar of Sinisa Vuk
Sinisa Vuk
Flag of Croatia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.