获得在焦炭垃圾数据*,而使用它作为缓冲功能(Getting trash data in char*

2019-10-28 23:26发布

我加载C ++中的德尔福DLL。 当我使用功能,使用char *为缓冲区(字符*给定的参数的程序)我只得到垃圾数据。 当我返回的char *功能一切都很好。

我是新来的C ++和我花了很多时间试图破解这个。 请帮忙。

一切都在下面的代码解释。 我已经把有3个功能exacly我的意思表示。

具有与缓冲问题实施例的功能是:DLL_PingConnection(VAR avXml:PChar类型):布尔值; - 返回true / false,如参数需要缓冲和功能在缓冲区做应该有有效的XML(但只有垃圾)

#include <windows.h> //this will load delphi dll
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string.h>

using namespace std;

// ------------------------------------------------ pointers on functions inside Delphi DLL (32 bits)
typedef bool(*TYPE_DLL_SetLicense)(char*, char*); //initialize dll stuff - I load licence from a file into char* - everything works fine
typedef bool(*TYPE_DLL_PingConnection)(char*); //the char* is buffer - I give empty char* as parameter and I should get correct xml with serwer data - I GET ONLY TRASH :(
typedef char*(*TYPE_DLL_ERR_DESCRIPTION)(void); //this function does not use buffer it returns char* - everything works fine

//so as you see problem is with buffers and function like this: DLL_PingConnection(buffer)

int main()
{

// ------------------------------------------------ Loading the library  
    HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\full_path\\SOMEDLL.dll");

    //checking the library
    if (hGetProcIDDLL == NULL) {std::cout << "Could NOT load the dynamic library" << std::endl;return EXIT_FAILURE;}
    else{std::cout << "dynamic library loaded" << std::endl;}

// ------------------------------------------------ START: resolving functions adresses

    TYPE_DLL_SetLicense DLL_SetLicense = (TYPE_DLL_SetLicense)GetProcAddress(hGetProcIDDLL, "DLL_SetLicense");
    if (!DLL_SetLicense) {std::cout << "Could NOT locate the function: DLL_SetLicense" << std::endl;return EXIT_FAILURE;}
    else{std::cout << "Function DLL_SetLicense located" << std::endl;}

    TYPE_DLL_PingConnection DLL_PingConnection = (TYPE_DLL_PingConnection)GetProcAddress(hGetProcIDDLL, "DLL_PingConnection");
    if (!DLL_PingConnection) {std::cout << "Could NOT locate the function: DLL_PingConnection" << std::endl;return EXIT_FAILURE;}
    else{std::cout << "Function DLL_PingConnection located" << std::endl;}

    TYPE_DLL_ERR_DESCRIPTION DLL_ERR_DESCRIPTION = (TYPE_DLL_ERR_DESCRIPTION)GetProcAddress(hGetProcIDDLL, "DLL_ERR_DESCRIPTION");
    if (!DLL_ERR_DESCRIPTION) {std::cout << "Could NOT locate the function: DLL_ERR_DESCRIPTION" << std::endl;return EXIT_FAILURE;}
    else{std::cout << "Function DLL_ERR_DESCRIPTION located" << std::endl;}        


std::cout << "\n\nInitialization over. \n\n" << std::endl;  


// ------------------------------------------------ START: calling functions from delphi dll       

//DLL_SetLicence - this function take buffer as parameter, but dont return anything into the buffer. All works fine.

    //start - we read licence from file
    char buffer_licence[1242];
    memset(buffer_licence,0,sizeof(buffer_licence));

//I read content of buffer_licence usinf ifstream from the file here (but I don't put the code, to keep sample minimal)

    //we set licence with dll function
    bool is_licence = DLL_SetLicense(buffer_licence,(char*)"");

    //the output
    if (is_licence == TRUE)
      std::cout << "Licence has been set\n";
    else
      std::cout << "Licence has been NOT set\n";




//DLL_PingConnection - it takes empty buffer as parameter, it should save xml into buffer but it saves only trash.

    //we try to save ping to the file - buffer
    char buffor_ping_xml[2000];
    memset(buffor_ping_xml,0,sizeof(buffor_ping_xml));

    //this should gieve proper xml, but it returns only trash.... please help
    bool is_ping = DLL_PingConnection(buffor_ping_xml);

    if(is_ping)
    {

        std::cout << "DLL_PingConnection True\n"; //function returned true, so it worked correct.

        std::cout << buffor_ping_xml; //but in the buffer is trash that I show on the screen. I also tried to put buffor_ping_xml info the file (diferent ways) but always result was trash just like on screen.

    }
    else
    {
        std::cout << "DLL_PingConnection False: \n";
    }           



//DLL_ERR_DESCRIPTION - if will automaticly return error description if there is any error to report. No buffer, no problems.

        std::cout << buffor_ping_xml; //the data on screet is fine, so is in file and everywhere else.



    return EXIT_SUCCESS;
}

PingConnection函数将返回只有这个,而不是良好的XML。

编辑:

Oroginally我用的Netbeans + MinGW的,但作为在意见提出我已经使用替代编译器:Borland的助洗剂C ++ 6.0,和Embarcadero的RAD工作室XE3(C ++生成器)。 这些问题保持不变,甚至你我使用的所有调用约定类型雷米勒博提及。

typedef bool(*TYPE_DLL_PingConnection)(char*); //standard calling convention default for compiler - returns trash
typedef bool(__cdecl *TYPE_DLL_PingConnection)(char*); //returns trash also
typedef bool(__stdcall *TYPE_DLL_PingConnection)(char*); //doesnt write anything to the buffer
typedef bool(__fastcall *TYPE_DLL_PingConnection)(char*); //returns trash

我曾经遇到过在C ++ Builder的小问题。 我不能在此环境下清理缓存:

memset(buffer,0,sizeof(buffer)); // will crash the program under c++ builder

尝试使用“字符*&”会使程序崩溃也。

typedef bool(__cdecl *TYPE_DLL_PingConnection)(char*&);
OR
typedef bool(__stdcall *TYPE_DLL_PingConnection)(char*&);
OR
typedef bool(__fastcall *TYPE_DLL_PingConnection)(char*&);

char * buffer;
bool is_ping = DLL_PingConnection(buffer);

使用char **会引起缓冲区类型不匹配。

EDIT2:

根据要求由大卫赫弗南我并附上文件的样本。 重要的部分是trasnated为英语。 剩下的只是XLM是PIngConnection应返回的结构。 没有太多的帮助,有 - 整个文档是这个样子。

PS:我问过类似的问题在这里: 垃圾字符使用C ++缓冲区时 -基于wxWidgets的代码(我虽然wxWidgets的创建问题,但它并不也许会有人发现wxWidgets的代码有用的你)。

编辑3:

我设法得到有关DLL的更多信息。

德尔福版本是7。

可以肯定的呼叫类型是STDCALL。 (DLL_PingConnection:函数(VAR avXml:PChar类型):布尔型; STDCALL)

这是怎么从这个DLL中的函数被调用德尔福:

lPointer := nil;  //pointer
lOSOZPointer := nil; //pointer
lpXML := nil; //pChar

lpXML:=StringToPChar(lXML);
lPointer := lpXML;

lWynik:=OSOZ_GetServerDataTime(lpXML);
if lWynik then
begin
  lOSOZPointer := lpXML;
  //akcja na wyniku
end;

if lPointer <> nil then begin
  Freemem(lPointer);
end;
if lOSOZPointer <> nil then begin
  OSOZ_FreeMem(lOSOZPointer);
end;

Answer 1:

DLL_PingConnection(VAR avXml:PChar类型):布尔值;

这不是一个完整的声明。 很显然,这是一个function ,因为它有一个Boolean返回类型。 -但它也声明调用约定以及stdcall__stdcall在C / C ++)或cdecl__cdecl在C / C ++)? 如果没有,那么它使用Delphi的默认register约定,而不是(这是__fastcall仅在Borland公司/ CodeGear的/ Embarcadero的C ++编译器,但在任何其他C / C ++编译器没有等价物)。 您现有的typedef使用的是C ++编译器的默认调用约定,通常是__cdecl 。 调用约定不匹配与使用DLL的最常见的问题,因为它会导致调用堆栈,从而影响参数的传递方式,访问和清理的管理不善。

此外,在该DLL写的是什么版本的Delphi? PCharPAnsiCharchar* C ++中)在2007年德尔福,但PWideCharwchar_t* C ++中)在2009年和以后德尔福。 机会是,由于数据是XML,然后PAnsiChar / char*很可能被使用。

此外, PChar参数被作为传递var在Delphi声明,这是相同的在C语言的指针和在C ++中的参考。

你为了使用C / C ++代码这个DLL功能需要的信息,这些重要的部分。 除非文档显式声明这些细节,或DLL具有C / C ++的.h / .HPP显示实际申报文件,那么你可以做的最好的是猜测,并给予你已经证明这样不完整的申报有可能的几种变化远:

char*&可以替换char**如果需要):

typedef bool (__cdecl *TYPE_DLL_PingConnection)(char*&);

typedef bool (__stdcall *TYPE_DLL_PingConnection)(char*&);

typedef bool (__fastcall *TYPE_DLL_PingConnection)(char*&);

typedef bool (__cdecl *TYPE_DLL_PingConnection)(wchar_t*&);

typedef bool (__stdcall *TYPE_DLL_PingConnection)(wchar_t*&);

typedef bool (__fastcall *TYPE_DLL_PingConnection)(wchar_t*&);

如果DLL函数使用cdeclstdcall ,那么一切都OK,因为大多数C / C ++编译器支持的调用约定。 但是,如果DLL函数使用register来代替,如果你没有使用Borland公司/ CodeGear的/ Embarcadero的C ++编译器,那么你就SOL。 你必须来包装出口使用更轻便的签名包装功能的另一个德尔福写的DLL中的DLL。



文章来源: Getting trash data in char* while using it as buffer in function