2010-08-24 9 views
0

Я хочу использовать dll из ssdeep (http://ssdeep.sourceforge.net/). API:Использование C/C++ DLL в Delphi 2010

int fuzzy_hash_buf (unsigned char * buf, uint32_t buf_len, char * result);

то в Delphi, я пишу это следующим образом:

функция fuzzy_hash_buf (БУФ: PByte; buf_len: Кардинал; результат: PAnsiChar): целое число; STDCALL; external 'fuzzy.dll' name 'fuzzy_hash_buf';

Как использовать эту функцию в Delphi?

Спасибо!

ответ

1

Если fuzzy.dll экспортирует функцию fuzzy_hash_buf с декларацией C

int fuzzy_hash_buf(unsigned char *buf, uint32_t buf_len, char *result); 

, то вы правы, что декларация Delphi будет

function fuzzy_hash_buf(buf: PAnsiChar; buf_len: cardinal; result: PAnsiChar): 
    integer; 

Чтобы использовать эту функцию в Delphi, в interface секции блок, написать сообщение

function fuzzy_hash_buf(buf: PAnsiChar; buf_len: cardinal; result: PAnsiChar): 
    integer; stdcall; 

п, в implementation части той же единицы, вы не реализуете функцию самостоятельно, а указывать на внешний DLL:

function fuzzy_hash_buf; external 'fuzzy.dll' name 'fuzzy_hash_buf` 

Обратите внимание, что вы не должны переопределить параметры, тип результата, и вызывающего соглашения (stdcall).

Теперь вы можете использовать эту функцию, как если бы она была фактической функцией этого устройства. Например, вы могли бы написать

val := fuzzy_hash_buf(buf, len, output); 

из любого блока, который uses блок, в котором вы объявленную fuzzy_hash_buf.

Update

Я боюсь, что я не достаточно хорошо знаком с функцией CreateFileMapping. Однако, после прочтения документации MSDN, я считаю, что вы можете сделать

var 
    buf: PAnsiChar; 

buf := MapViewOfFile(FFileMappingHandle, FILE_MAP_READ, 0, 0, 0); 

// Now, if I have understood MapViewOfFile correctly, buf points to the first byte of the file. 

var 
    StatusCode: integer; 
    TheResult: PAnsiChar; 

GetMem(TheResult, FUZZY_MAX_RESULT); 

StatusCode := fuzzy_has_buf(buf, FFileSize, TheResult); 

// Now TheResult points to the first byte (character) of the output of the function. 
+0

Спасибо, Андреас, я знаю это. У меня есть буфер из файла (прочитайте с помощью CreateFile, CreateFileMapping), как передать этот буфер в первый параметр? Благодаря! – MrKimbo

+0

Нет, я знаю, как использовать CreateFileMapping, проблема не в этом. Я имею в виду, как передать файл-буфер в fuzzy_hash_buf (buffer ..). Я попробовал. Посмотрите мой код: GetMem (Ssdeep, FUZZY_MAX_RESULT); GetMem (Ssdeep_Buf, FFileSize); Ssdeep_Buf: = @PAnsiChar (FFileMappingPtr) [0]; Hash.Ssdeep: = AnsiString (fuzzy_hash_buf (Ssdeep_Buf, FFileSize, Ssdeep)); Результат: нарушение доступа ОШИБКА. Я не знаю, где проблема. – MrKimbo

+0

Что такое 'FFileMappingPtr'? Если это «buf» моего кода выше, просто используйте это как первый аргумент 'fuzzy_hash_buf'. Тогда 'FFileMappingPtr' является указателем (* * *), поэтому вам не нужно брать адрес этого (используя' @ '). Кроме того, часть '[0]' выглядит очень странно. Наконец, 'fuzzy_hash_buf' возвращает код состояния, а не строку. Строка записывается в буфер последнего параметра! –

1

Помимо возможности иметь соглашение о вызовах неправильно (stdcall или cdecl), это выглядит, как вы заявили, что правильно функционировать.

Основываясь на именах и типах параметров, мой догадка заключается в том, что вы должны передать указатель на массив байтов в первом параметре, а во втором - указать, сколько байтов вы используете, он дал это. Вы также передаете указатель на массив символов, который функция заполнит для вас. Размер этого массива равен . Предполагается, что будет достаточно большим, чтобы удерживать все функции, которые будут там установлены. Результат функции, вероятно, является кодом состояния, указывающим на успех или неудачу.

Консалтинг the documentation показывает, что мои догадки верны. Буфер результатов должен быть не менее FUZZY_MAX_RESULT байтов.Вы могли бы получить, что при объявлении массива символов:

var 
    HashResult: array[0..Fuzzy_Max_Result] of AnsiChar; 

Пасс, что функции:

status := fuzzy_hash_buf(buffer, buffer_length, HashResult); 
if status <> 0 then 
    Abort; 
HashResult[Fuzzy_Max_Result] := #0; 
ShowMessage(HashResult); 

документация не говорит ничего об обеспечении того, чтобы в результате буфер завершается нулем, так мы резервируем дополнительный байт в конце, а затем помещаем туда нулевой символ. Это позволяет безопасно передавать буфер результатов таким функциям, как ShowMessage, которые ожидают string параметров.

+0

Hi Rob, Спасибо за ответ! Да, вы прав, но я до сих пор не знаю, как передать первый параметр. Буфер из файлового буфера, например: FFileHandle: = CreateFile (PWideChar (WideString (FFileName)), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); , если FFileHandle <> INVALID_HANDLE_VALUE затем FFileMappingHandle: = CreateFileMapping (FFileHandle, nil, PAGE_READONLY, 0, FFileSize, nil); Теперь у меня есть буфер файлов, но как передать его первому параметру (буфере)? Спасибо! – MrKimbo

+0

У вас нет буфера. У вас есть дескриптор сопоставления файлов. Чтобы получить адрес буфера, вам нужно вызвать «MapViewOfFile». Но если вы хотите хэшировать весь файл, используйте функцию хеширования файлов вместо функции хэширования памяти: 'fuzzy_hash_filename'. –

+0

Да, у меня есть MapViewOfFile. Fuzzy_hash_filename выполняется нормально, но в этом случае я хочу использовать fuzzy_hash_buf, поэтому я могу определить размер буфера (а не весь файл). – MrKimbo

Смежные вопросы