Более быстрый параметр, передаваемый в Delphi / C - PullRequest
3 голосов
/ 26 сентября 2011

У меня есть 2 части приложения, Delphi и C, и у меня есть 2 вопроса 1. Какой самый быстрый способ передачи параметров в Delphi?

procedure name(Data: string); // Data is Copied to another location before passing so its slow
procedure name(var Data: string); // Data is Passed by pointer, Faster
procedure name(const Data: string); // unknown
  1. я хочу передать параметры указателями в c, у меня есть массив символов и функция, я не хочу передавать весь массив, вырезать его первую часть и передать остальные

    void testfunction(char **Data)
    {
        printf("Data = %d\n", *Data);
        return;
    }
    
    int main()
    {
        char Data[] = "TEST FUNCTION";
        testfunction(&&Data[4]);        // Error
        return 0;
    }
    

спасибо

Ответы [ 4 ]

6 голосов
/ 26 сентября 2011

Строки Delphi находятся в куче и всегда передаются по указателю.Ваш первый пример передачи по значению неверен.Строки, переданные по значению, не копируются.Только ссылка копируется.Это возможно для строк, потому что они имеют магическое поведение копирования при записи.Динамический массив, переданный по значению, копируется.

Использование const при передаче строки имеет лучшую производительность, поскольку компилятор может оптимизировать код подсчета ссылок.

Ваш код на C несколько запутан.Вы не хотите char**, скорее вы хотите char*.Помните, что строка C, char*, - это просто указатель на завершенный нулем блок памяти.Вам не нужно брать указатель на строку C, поскольку она уже является указателем.

И, конечно, вы имеете в виду %s, а не %d.Чтобы передать строку C, начинающуюся с 5-го символа, напишите Data+4.

 void testfunction(char *Data) {
     printf("Data = %s\n", Data);
 }

int main() {
    char Data[] = "TEST FUNCTION";
    testfunction(Data+4);
    return 0;
}
3 голосов
/ 27 сентября 2011

Никто не делал акцент на хорошо известном факте, что начиная с Delphi 2009, string = UnicodeString будет экспортироваться как PWideChar / LPCWSTR, а не PChar / LPCSTR. Стоит отметить ИМХО, потому что это может сбивать с толку, если оно недостаточно ясно для вас, и ожидать, что ваш код будет работать со всеми версиями Delphi.

Если вы хотите изменить содержимое строки из библиотеки C, вам, возможно, следует использовать тип WideString Delphi вместо string. WideString выделяется и обрабатывается Windows (это строка COM / Ole), поэтому у вас есть все соответствующие API C для обработки этих указателей OLESTR. И это WideString не страдает от разрыва Delphi 2009 Unicode (это всегда был Unicode).

Конечно, WideString медленнее, чем string (по нескольким причинам, главная из них - гораздо более медленное выделение кучи для WideString - улучшается с Vista), но это, ИМХО, безопасный мультиязычный способ экспорта некоторых текстовых данных в и из приложения и библиотеки Delphi (в мире Windows). Например, миру .Net понравится маршалинг таких переменных OLESTR.

2 голосов
/ 26 сентября 2011

Код немного вводит в заблуждение, я думаю. Намерен ли он печатать только «FUNCTION»? Если так:

void testfunction(const char *Data)
{
    printf("Data = %s\n", Data);
    return;
}

int main()
{
    char Data[] = "TEST FUNCTION";
    testfunction(Data+4);
    return 0;
}

Это передаст строку этой функции из индекса 4 (включая) в массиве в остальную часть. Передавая char *, вы не копируете строку в локальный стек этой функции. Просто указатель на начало этой памяти.

1 голос
/ 26 сентября 2011

Я могу ответить только на часть delphi (мой C немного ржавый сейчас, а ссылки на указатели / массивы C вызывают у меня головную боль, когда я am актуален и обновлен)

Строки являются указателями и ВСЕГДА передаются по ссылке, поэтому при передаче -EVER данные не копируются.

Однако в случае

procedure test(s:String);

Указатель S передается, иесли вы изменяете S в тесте процедуры, генерируется уникальная строка и новый указатель присваивается S, но не передается исходная переменная.Вы можете передавать строковые литералы и строковые выражения / изменяться на лету (s + 'bla bla bla')

procedure test(var s: String);

адрес указателя S передан,

указатель S передани если вы измените S внутри процедуры теста, генерируется уникальная строка (если требуется), и новый указатель присваивается S, и исходная переданная переменная.Вы НИКОГДА не можете передавать строковые литералы и строковые выражения / изменяться на лету (s + 'bla bla bla')

procedure test(const s: string);

Указатель S пропущен, и вы не можете изменять S в течение периода проверки процедуры.(хорошо, вы можете облажаться и обмануть компилятор, но это уродливо и сложно, и обычно требует много приведения типов)

...