Delphi和使用Teamspeak SDK读取返回的多维数组

Delphi和使用Teamspeak SDK读取返回的多维数组,delphi,Delphi,我试图从TeamSpeak3 SDK读取返回的数组,其中一些方法返回的数组以null结尾,并且是多维数据类型的混合数组 我应该传递什么“delhpi”结构作为参数,如何读取匹配结构中返回的值?a洛杉矶 type TDeviceInfo = record DeviceId : string; // maybe an integer DeviceName : string; end; TDeviceInfoArr = array of TDeviceInfo //

我试图从TeamSpeak3 SDK读取返回的数组,其中一些方法返回的数组以null结尾,并且是多维数据类型的混合数组

我应该传递什么“delhpi”结构作为参数,如何读取匹配结构中返回的值?a洛杉矶

type
  TDeviceInfo = record
    DeviceId : string; // maybe an integer
    DeviceName : string;
  end;

  TDeviceInfoArr = array of TDeviceInfo

  // or maybe
  TDeviceInfoArr = array of array[0..1] of string; 

var
  DeviceArr : array of TDeviceInfoArr;
这就是SDK文档所说的

要获取指定模式下所有可用播放和捕获设备的列表,请调用

unsigned int ts3client_getPlaybackDeviceList(modeID,result);
常量字符*modeID;
字符****结果;
未签名的int ts3client_getCaptureDeviceList(modeID,result);
常量字符*modeID;
字符****结果;
参数
•modeID
定义要使用的播放/捕获模式。对于不同的模式,可能会有不同的设备列表。有效模式由
ts3client_getDefaultPlayBackMode/s3client_getDefaultCaptureMode和ts3client_getPlaybackModeList/ts3client_getCaptureModeList

•结果
接收以NULL结尾的数组{{char*deviceName,char*deviceID},{char*deviceName,char*deviceID},…,NULL}的变量的地址。
除非函数返回错误,否则需要使用ts3client_freeMemory释放数组元素和数组本身。
成功时返回ERROR_ok,否则返回public_errors.h中定义的错误代码。发生错误时,结果数组未初始化,不能释放

查询所有可用播放设备的示例:

char*defaultMode;
如果(ts3client\u getDefaultPlayBackMode(&defaultMode)=错误\u确定){
字符***数组;
如果(ts3client\u getPlaybackDeviceList(默认模式和阵列)=错误\u确定){
for(int i=0;数组[i]!=NULL;++i){
printf(“播放设备名称:%s\n”,数组[i][0]);/*第一个元素:设备名称*/
printf(“播放设备ID:%s\n”,数组[i][1]);/*第二个元素:设备ID*/
/*自由元素*/
ts3client_freemory(数组[i][0]);
ts3client_freemory(数组[i][1]);
ts3client_freeMemory(数组[i]);
}
ts3client_freemory(数组);/*释放完整数组*/
}否则{
printf(“获取播放设备列表时出错\n”);
}
}否则{
printf(“获取默认播放模式时出错\n”);
}

首先,我将忽略错误处理,因为我认为在您的最后一个问题中我们已经处理了错误处理。我将假设
ts3client\u getDefaultPlayBackMode
不会出现任何问题

这样就剩下了
ts3client\u getPlaybackDeviceList
。按如下方式导入:

function ts3client_getPlaybackDeviceList(modeID: PAnsiChar; 
  out result: PPPAnsiChar): Cardinal; cdecl; external '...';
您可能需要定义
PPPAnsiChar

type
  PPPAnsiChar = ^PPAnsiChar;
  PPAnsiChar = ^PAnsiChar;
您可能会发现RTL已经定义了
PPAnsiChar

type
  PPPAnsiChar = ^PPAnsiChar;
  PPAnsiChar = ^PAnsiChar;
因此,接下来调用函数。首先声明一个变量来保存数组,然后声明其他变量来帮助迭代:

var
  arr, myarr: PPPAnsiChar;
  p: PPAnsiChar;
然后调用函数:

ts3client_getPlaybackDeviceList(modeID, arr);
myarr := arr;
while myarr^ <> nil do
begin
  p := myarr^;
  Writeln('Playback device name: ', p^);
  ts3client_freeMemory(p^);
  inc(p);
  Writeln('Playback device ID: ', p^);
  ts3client_freeMemory(p^);
  ts3client_freeMemory(myarr^);
  inc(myarr);
end;
ts3client_freeMemory(arr);
ts3client\u getPlaybackDeviceList(modeID,arr);
myarr:=arr;
而我却没有
开始
p:=myarr^;
Writeln('播放设备名称:',p^);
TS3客户端空闲内存(p^);
公司(p),;
Writeln('播放设备ID:',p^);
TS3客户端空闲内存(p^);
TS3客户端空闲内存(myarr^);
公司(myarr);
结束;
TS3客户端空闲内存(arr);
这个代码真的很卑鄙,我相信你会同意的。如果您有一个现代版本的Delphi,那么您可以启用指针数学,使其可读性更好

{$POINTERMATH ON}

ts3client_getPlaybackDeviceList(modeID, arr);
i := 0;
while arr[i] <> nil do
begin
  Writeln('Playback device name: ', arr[i][0]);
  Writeln('Playback device ID: ', arr[i][1]);
  ts3client_freeMemory(arr[i][0]);
  ts3client_freeMemory(arr[i][1]);
  ts3client_freeMemory(arr[i]);
  inc(i);
end;
ts3client_freeMemory(arr);
{$POINTERMATH ON}
TS3客户端\u获取播放设备列表(modeID,arr);
i:=0;
而我什么都不做
开始
Writeln('播放设备名称:',arr[i][0]);
Writeln('播放设备ID:',arr[i][1]);
ts3client_freemory(arr[i][0]);
ts3client_freeMemory(arr[i][1]);
ts3client_freeMemory(arr[i]);
公司(一);
结束;
TS3客户端空闲内存(arr);
虽然这个代码更好,但它永远不会赢得选美比赛


记住,我忽略了所有的错误检查。您需要添加这些内容。

根据David的建议,我发现以下代码正常工作,谢谢David

{$POINTERMATH ON}
procedure TfrmMain.RequestPlaybackDevices;
var
  arr, myarr: PPPAnsiChar;
  p: PPAnsiChar;
  defaultmode : PAnsiChar;
  i : Integer;
begin
  try
    ts3check(ts3client_getDefaultPlayBackMode(@defaultmode));
    ts3check(ts3client_getPlaybackDeviceList(defaultMode, @arr));
    try
      i := 0;
      while arr[i] <> nil do
      begin
        LogMsg(format('Playback device name: %s',[UTF8ToUnicodeString(arr[i][0])]));
        LogMsg(format('Playback device ID: %s',[UTF8ToUnicodeString(arr[i][1])]));
        ts3client_freeMemory(arr[i][0]);
        ts3client_freeMemory(arr[i][1]);
        ts3client_freeMemory(arr[i]);
        inc(i);
      end;
    finally
      ts3client_freeMemory(arr);
    end;
  except
    on e: exception do LogMsg(Format('Error RequestPlaybackDevices: %s', [e.Message]));
  end;
end;
{$POINTERMATH OFF}
{$POINTERMATH ON}
程序TfrmMain.RequestPlaybackDevices;
变量
阿,玛雅:帕潘西卡;
p:PPAnsiChar;
默认模式:PAnsiChar;
i:整数;
开始
尝试
ts3check(ts3client_getDefaultPlayBackMode(@defaultmode));
ts3check(ts3client_getPlaybackDeviceList(defaultMode,@arr));
尝试
i:=0;
而我什么都不做
开始
LogMsg(格式('播放设备名称:%s',[UTF8ToUnicodeString(arr[i][0]));
LogMsg(格式('playbackdeviceid:%s',[UTF8ToUnicodeString(arr[i][1]));
ts3client_freemory(arr[i][0]);
ts3client_freeMemory(arr[i][1]);
ts3client_freeMemory(arr[i]);
公司(一);
结束;
最后
TS3客户端空闲内存(arr);
结束;
除了
在e:exception do LogMsg(格式('Error RequestPlaybackDevices:%s',[e.Message]);
结束;
结束;
{$POINTERMATH OFF}

在您的第一个解决方案中:我们有一个指向内存位置(myarr)的指针,该指针指向具有deviceinfo(名称)的第一个(p)元素的指针。因此,每次移动myarr指针时,我们都需要移动deviceinfo指针p one来获取deviceid。六羟甲基三聚氰胺六甲醚。。。。锅炉板。。。第二个解决方案看起来像Delphi:)只需移动主指针,就显得更加“直接”。现在我只剩下一个问题了,那就是如何构建相同的结构,将其解析到SDK中——但这将是一个新问题。非常感谢-非常非常有用!那么,你是法国自行车手吗?什么。。你认为我的行为像一个??)不,我是丹麦自行车手;)如果你指的是我的阿凡达,那么它是在我第三次爬上文图克斯山后被捕获的。有一天,我是这个独家俱乐部的骄傲成员,我甚至没有做过一次Ventoux,尽管我经常在看得见的地方度假。我认识那个俱乐部的另一个人。努力加入!不,这一点都不容易,但如果你想的话是可行的,如果你喜欢骑自行车,你应该去做,这是一种极端的体验