Проблемы с вызовом параметра Delphi DLL IStream из C ++ - PullRequest
1 голос
/ 28 апреля 2019

У меня есть DLL, написанная на Delphi.У меня есть только DLL без заголовочного файла, поэтому я загружаю его динамически.(для проекта C ++)

HMODULE hLib = LoadLibrary(L"LibName.dll");
if (!hLib) {
//Throw error
}

DLL предоставляет функции:

function DataToFile(AddressName: PChar; Request: PChar;
  RequestSize: integer; ResultFile: PChar;
  ErrorBuf: PChar; ErrorBufSize: integer):BOOL;stdcall;

function DataToStream(AddressName: PChar; Request: PChar;
  RequestSize: integer; ResultStream: IStream;
  ErrorBuf: PChar; ErrorBufSize: integer):BOOL;stdcall;

Мой код Visual Studio (C ++):

typedef bool(__stdcall* f_DataToFile)(
    char*,  //AddressName: PChar
    char*,  //Request: PChar
    int,    //RequestSize: integer
    char*,  //FileName: PChar
    char*,  //ErrorBuf: PChar
    int);   //ErrorBufSize: integer);

typedef bool(__stdcall* f_DataToStream)(
    char*,  //AddressName: PChar
    char*,  //Request: PChar
    int,    //RequestSize: integer
    std::istream &, //ResultStream: IStream
    char*,  //ErrorBuf: PChar
    int);   //ErrorBufSize: integer);

... Получите функцию.адрес:

//load DataToFile
f_DataToFile DataToFile = (f_DataToFile) GetProcAddress(hLib, "DataToFile");
if (!DataToFile) { //throw error 
}

//load DataToStream
f_DataToStream DataToStream = (f_DataToStream) GetProcAddress(hLib, "DataToStream");
if (!DataToStream) { //throw error
}

... Установить данные:

char* AddressName = _strdup("127.0.0.1:1234");  //AddressName: PChar
char* Request = _strdup("<?xml request... >");  //Request: PChar
int RequestSize = strlen(Request);  //RequestSize: integer

char* ResultFile = _strdup("exportpath\\output.xml");  //FileName: PChar
char* ErrorBuf = new char[255]; //ErrorBuf: PChar
int ErrorBufSize = 255;  //ErrorBufSize: integer);

std::filebuf(buffer);
std::istream ResultStream(&buffer);

... Первая функция работает правильно

bool reesult1= (DataToFile)(AddressName, Request, RequestSize, ResultFile, ErrorBuf, ErrorBufSize);

... У меня проблемы со второйвыполнение функции -

bool reesult2= (DataToStream)(AddressName, Request, RequestSize, ResultStream, ErrorBuf, ErrorBufSize);

Компилируется, но при запуске выдает Access Violoation.

Может кто-нибудь мне помочь получить - как правильно работать с типом данных IStream из (Delphi)?

Когда я объявляю ResultStream как указатель nullptr и вызываю функцию DataToStream с неверным адресом соединения, функция возвращает «Ошибка соединения» - поэтому она импортируется правильно, и основной вопрос - возвращение IStream из функции.

Ответы [ 2 ]

4 голосов
/ 28 апреля 2019

Ваш перевод IStream неверен. DLL использует интерфейс COM IStream . Вы не можете заменить это классом C ++ std::istream. Вам необходимо использовать COM-объект, который реализует интерфейс IStream. Чтобы получить доступ к файлу как IStream, вы можете использовать, например, функцию Win32 SHCreateStreamOnFileEx().

0 голосов
/ 07 мая 2019

Спасибо Реми Лебо!

HRESULT GetFileStream(
_In_ LPCWSTR fullFileName,
_Outptr_ IStream** stream)

{
HRESULT hr = S_OK;

// Create stream for writing the file
if (SUCCEEDED(hr))
{
    hr = SHCreateStreamOnFileEx(
        fullFileName,
        STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
        0, // default file attributes
        TRUE, // create file if it does not exist
        NULL, // no template
        stream);
}
return hr;
}

в typedef:

IStream *,  //ResultStream: IStream

..

LPCWSTR filename = L"path\\to\\file.txt";
IStream* ResultStream = NULL;
HRESULT hr = GetFileStream(filename, &ResultStream);

..

bool result = (CallRK7XMLRPCToStream)(AddressName, Request, RequestSize, ResultStream, ErrorBuf, ErrorBufSize);

Вот хороший пример использования SHCreateStreamOnFileEx:

https://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/AppxPackingCreateBundle/cpp/CreateBundle.cpp

...