Delphi - конвертировать (читать) C ++ NULL завершенный массив из вызова dll

0

Помогите, я схожу с ума :)

Я играю с TeamSpeak3 и получаю вызов dll, который возвращает массив клиентов (ID) в Интернете. Моя проблема в том, что она возвращается в структуре, которую я не могу понять, чтобы читать в Object Pascal.

В руководстве SDK указано следующее:


This is what the docs says
To get a list of all currently visible clients on the specified virtual server:
unsigned intts3client_getClientList(serverConnectionHandlerID, result);
uint64 serverConnectionHandlerID;
anyID** result;
Parameters
• serverConnectionHandlerID
ID of the server connection handler for which the list of clients is requested.
• result
Address of a variable that receives a NULL-termianted array of client IDs. Unless an error occurs, the array must be released
using ts3client_freeMemory.
Returns ERROR_ok on success, otherwise an error code as defined in public_errors.h. If an error has occured, the
result array is uninitialized and must not be released.

Это мой код Delphi.

type
  PPanyID = ^PAnyID;
  PanyID = ^anyID;
  anyID  = word;

// declaration looks like this, some guy called CodeJunkie ported it from C++)
function ts3client_getClientList(serverConnectionHandlerID: uint64; result: PPanyID): longword; cdecl; external CLIENT_DLL {$IFDEF MACOS}name '_ts3client_getClientList'{$ENDIF};
procedure TfrmMain.RequestOnlineClients;
var
  clientids : PAnyId;
  i : Integer;
begin

  error := ts3client_getClientList(FTSServerHandlerID, @clientids);
  if (error <> ERROR_ok) then
  begin
    if (ts3client_getErrorMessage(error, @errormsg) = ERROR_ok) then
    begin
      LogMsg(Format('Error requesting online clients: %s', [errormsg]));
      ts3client_freeMemory(errormsg);
    end;
  end else
      begin
         // Put in into some regular Object array here, but how the h...... 
         // Or at least interate the received array of ID's


      end;

end;

Пример кода в C++ выглядит так, и он работает, я его не писал :)

void showClients(uint64 serverConnectionHandlerID) {
    anyID *ids;
    anyID ownClientID;
    int i;
    unsigned int error;

    printf("\nList of all visible clients on virtual server %llu:\n", (unsigned long long)serverConnectionHandlerID);
    if((error = ts3client_getClientList(serverConnectionHandlerID, &ids)) != ERROR_ok) {  /* Get array of client IDs */
        printf("Error getting client list: %d\n", error);
        return;
    }
    if(!ids[0]) {
        printf("No clients\n\n");
        ts3client_freeMemory(ids);
        return;
    }

    /* Get own clientID as we need to call CLIENT_FLAG_TALKING with getClientSelfVariable for own client */
    if((error = ts3client_getClientID(serverConnectionHandlerID, &ownClientID)) != ERROR_ok) {
        printf("Error querying own client ID: %d\n", error);
        return;
    }

    for(i=0; ids[i]; i++) {
        char* name;
        int talkStatus;

        if((error = ts3client_getClientVariableAsString(serverConnectionHandlerID, ids[i], CLIENT_NICKNAME, &name)) != ERROR_ok) {  /* Query client nickname... */
            printf("Error querying client nickname: %d\n", error);
            break;
        }

        if(ids[i] == ownClientID) {  /* CLIENT_FLAG_TALKING must be queried with getClientSelfVariable for own client */
            if((error = ts3client_getClientSelfVariableAsInt(serverConnectionHandlerID, CLIENT_FLAG_TALKING, &talkStatus)) != ERROR_ok) {
                printf("Error querying own client talk status: %d\n", error);
                break;
            }
        } else {
            if((error = ts3client_getClientVariableAsInt(serverConnectionHandlerID, ids[i], CLIENT_FLAG_TALKING, &talkStatus)) != ERROR_ok) {
                printf("Error querying client talk status: %d\n", error);
                break;
            }
        }

        printf("%u - %s (%stalking)\n", ids[i], name, (talkStatus == STATUS_TALKING ? "" : "not "));
        ts3client_freeMemory(name);
    }
    printf("\n");

    ts3client_freeMemory(ids);  /* Release array */
}

Пожалуйста, может кто-нибудь помочь здесь?

Теги:

2 ответа

0
Лучший ответ

Указатель, который вы возвращаете, указывает на первый результат. Doing Inc(clientids) переводит вас на следующий результат. Продолжайте, пока не дойдете anyid, что равна нулю ( "NULL").

(Вам также необходимо сохранить исходное значение clientids чтобы вы могли передать его свободной функции, как указано в документации, чтобы избежать утечки памяти.)

0

G это действительно так, серьезно ли это единственный способ чтения массивов, возвращаемых из c++ dll? И будет ли это работать с 64-битным тоже?

procedure TfrmMain.RequestOnlineClients;
var
  ids : array of anyID;
  pids : PanyID;
  aid : anyID;
begin


  error := ts3client_getClientList(FTSServerHandlerID, @ids);
  if (error <> ERROR_ok) then
  begin
    if (ts3client_getErrorMessage(error, @errormsg) = ERROR_ok) then
    begin
      LogMsg(Format('Error requesting online clients: %s', [errormsg]));
      ts3client_freeMemory(errormsg);
    end;
  end else
      begin
         pids := @ids[0];
         while (pids^ <> 0) do
         begin
           aid := pids^;
           LogMsg(format('id %u',[aid]));
           inc(pids);
         end;
         ts3client_freeMemory(@pids^);
      end;
end;
  • 0
    Ваша обработка ошибок отключена. Не вызывайте ts3client_freeMemory при сбое вызова функции. В документации это ясно сказано. Этот API очень хорошо определен. Я не думаю, что вы должны жаловаться на это.
  • 0
    Также вместо pids := @ids[0]; написать pids := ids;
Показать ещё 10 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню