如何在delphi中创建文件并将其传递到C DLL并在回调中使用该文件?

在ExportToFileCallback中,我想使用在SaveMsg中分配的文件,但似乎无法从指向FilePCDMsg的指针中获取该文件。

type
  FilePCDMsg  = File of PcdkMsg;    
  PFilePCDMsg = ^FilePCDMsg;


procedure TfrmMain.SaveMsg( pMsg: PcdkMsg; fn: String = '' );
var
  myFile: FilePCDMsg;
  pFile : PFilePCDMsg;
begin
  if fn.IsEmpty then
    fn := TPath.GetTempFileName;
  CodeSite.Send( 'SaveMsg fn',fn );

  AssignFile( myFile,fn );
  Rewrite( myFile );
  pFile := Addr( myFile );
  cdkMsgExport( pMsg,ExportToFileCallBack,pFile );
end;

function ExportToFileCallBack( pData: PUInt8; len: UInt32; pUser: Pointer ): Integer; cdecl;
var
  pFile : PFilePCDMsg;
  myFile: FilePCDMsg;
begin
  // this is the C code for what I want to do
  // return fwrite(pData,1,len,(FILE*)pUser) == len;
  pFile  := PFilePCDMsg( pUser );
  myFile := FilePCDMsg( pFile ); // will not compile
end;

此DLL由第三方提供,并且具有执行操作的回调。在这里,我试图查询摄像机的配置,并且回叫了三次。我认为它正在将要我追加到我已分配的文件的数据传回给我。

这是我要在Delphi中复制的C代码。

#ifdef WIN32
#include <windows.h>
#include "../../include/external/stdint.h"
#include "../../include/external/inttypes.h"
#endif

#ifdef LINUX
#include <stdlib.h> 
#include <unistd.h>
#include <stdint.h>
#include <inttypes.h>
#endif

#include <stdio.h>


#include "../../include/cdk.h"

const char* strAddress = NULL;
uint16_t uPort = 10001;
const char* strOptions = NULL;
const char* strPathOut = ".";


void help()
{
    printf("Command line:\n");
    printf("   receive address [-port port] [-options options] [-output outputpath]\n");
    printf("   Port default value : 10001\n");
    printf("   Output path default value : .\n");
}

int parseCommandLine(int argc,char* argv[])
{
    int i;

    if (argc < 2)
    {
        return 0;
    }

    strAddress = argv[1];

    for (i=2;i<argc;++i)
    {
        if (strcmp(argv[i],"-port") == 0)
        {
            ++i;
            if (i >= argc)
                return 0;
            uPort = atoi(argv[i]);
        }
        else if (strcmp(argv[i],"-options") == 0)
        {
            ++i;
            if (i >= argc)
                return 0;
            strOptions = argv[i];
        }
        else if (strcmp(argv[i],"-output") == 0)
        {
            ++i;
            if (i >= argc)
                return 0;
            strPathOut = argv[i];
        }
    }

    return 1;
}



void traceCallback(cdk* pSrc,unsigned char level,const char* strTrace,void* pUser ) 
{ 
    printf("[%u] %s\n",level,strTrace);
}

int32_t exportToFileCallback(const uint8_t* pData,uint32_t len,void* pUser)
{
    return fwrite(pData,(FILE*)pUser) == len;      
}

void parseConfig(cdkMsg *pMsg)
{
    cdkMsgElement* peltConfig = NULL;
    cdkMsgElement* peltDevice = NULL;
    cdkMsgElement* peltCameras = NULL;
    const char* str;
    uint32_t i = 0;
    uint32_t j = 0;


    peltConfig = cdkMsgChild(pMsg);
    if(NULL == peltConfig)
    {
        return;
    }
    peltDevice = cdkMsgElementFirstChild(peltConfig,"device");
    if (NULL != peltDevice )
    {
        str = cdkMsgElementAttributeValue(peltDevice,"name");
        if (str)
            printf("Name : %s\n",str);
    }
    peltCameras = cdkMsgElementFirstChild(peltConfig,"cameras");
    if (NULL != peltCameras )
    {
        cdkMsgElement* peltCamera = cdkMsgElementFirstChild(peltCameras,NULL);
        cdkMsgElement* peltCameraParam = NULL;
        while(peltCamera)
        {
            /* camera attributes */
            printf("%s : \n",cdkMsgElementName(peltCamera));
            for(i = 0; i < cdkMsgElementAttributeCount(peltCamera); i++)
            {
                str = cdkMsgElementAttributeName(peltCamera,i);
                printf("* \t %s : %s\n",str,cdkMsgElementAttributeValue(peltCamera,str));
            }

            /* camera parameters */
            peltCameraParam = cdkMsgElementFirstChild(peltCamera,NULL);
            while(peltCameraParam)
            {
                printf("* \t %s : \n",cdkMsgElementName(peltCameraParam));

                for(j = 0; j < cdkMsgElementAttributeCount(peltCameraParam); j++)
                {
                    str = cdkMsgElementAttributeName(peltCameraParam,j);
                    printf("** \t\t %s : %s\n",cdkMsgElementAttributeValue(peltCameraParam,str));
                }

                peltCameraParam = cdkMsgElementNextChild(peltCamera,peltCameraParam,NULL);
            }

            peltCamera = cdkMsgElementNextChild(peltCameras,peltCamera,NULL);
        }


    }
}

int main(int argc,char* argv[])
{
    cdk* pcdk = NULL;
    FILE* pFile = NULL;
    char strFileName[256];
    cdkMsg * pMsgRequest = NULL;
    cdkMsg * pMsgAnswer = NULL;

    cdkSetTraceFunction(traceCallback,NULL);

    printf("App launched\n");
    printf("cdk version : %s\n",cdkGetVersion()); 

    /* command line */
    if (!parseCommandLine(argc,argv))
    {
        help();
        return -1;
    }

    printf("Get config from %s:%u in %s\n",strAddress,uPort,strPathOut);
    if (strOptions)
    {
        printf("   Options : %s\n",strOptions);
    }

    pcdk = cdkCreate();
    if (!cdkBind(pcdk,strOptions))
    {
        printf("cdkBind failed : %s\n",cdkGetLastError(pcdk));
        goto labelEnd;
    }
    if(!cdkWaitForConnection(pcdk,30000))
    {
        printf("ERROR : %s\n",cdkGetLastError(pcdk));
        goto labelEnd;
    }

    /* get config */
    pMsgRequest = cdkMsgCreate();
    cdkMsgSetChild(pMsgRequest,cdkMsgElementCreate("getconfig"));

    pMsgAnswer = cdkSendRequest(pcdk,pMsgRequest,30000);
    cdkMsgDestroy(pMsgRequest);
    if (NULL == pMsgAnswer )
    {
        printf("ERROR : %s\n",cdkGetLastError(pcdk));
        goto labelEnd;
    }

    /* export config msg */
    sprintf(strFileName,"%s/config.cdkmsg",strPathOut);
    pFile = fopen(strFileName,"wb");
    if (NULL == pFile)
    {
        printf("Unable to create output file,does the output path exist?");
        goto labelEnd;
    }
    if (!cdkMsgExport(pMsgAnswer,&exportToFileCallback,pFile))
    {
        printf("Message export failed : %s",cdkGetLastError(pMsgAnswer));
        goto labelEnd;
    }

    /* Parse config */
    parseConfig(pMsgAnswer);



labelEnd:

    if (pFile)
    {
        fclose(pFile);
    }
    if (pMsgAnswer)
    {
        cdkMsgDestroy(pMsgAnswer);
    }
    if (pcdk)
    {
        cdkDestroy(pcdk);
    }   

    return 0;


}
mingdou 回答:如何在delphi中创建文件并将其传递到C DLL并在回调中使用该文件?

我想得太多了。答案其实很简单

procedure TfrmMain.SaveMsg(pMsg: PCDKMsg);
begin
  CDKMsgExport( pMsg,ExportToFileCallBack,nil );
end;

function ExportToFileCallBack( pData: PUInt8; len: UInt32; pUser: Pointer ): Integer; cdecl;
var
  FileName: string;
  Stream  : TStream;
begin
  FileName := 'Config.xml';
  if TFile.Exists( FileName ) then
    Stream := TFileStream.Create( FileName,fmOpenReadWrite )
  else
    Stream := TFileStream.Create( FileName,fmCreate );
  try
    Stream.Seek( 0,soFromEnd );
    Stream.WriteBuffer( Pointer( pData )^,len );
    CodeSite.SendStreamAsText( 'ExportToFileCallBack',Stream );
  finally
    Stream.Free;
  end;
end;

非常感谢您的帮助

,

在过程TfrmMain.SaveMsg中:

myFile:FilePCDMsg;是一个LOCAL变量(保存在堆栈中)。

因此,当TfrmMain.SaveMsg执行完成时,文件引用myFile将不再有效,因此指针 传递给CDKMsgExport()的pFile将会失效!

这是最大的问题!

一个较小的问题是语法:

myFile:= FilePCDMsg(pFile); //无法编译

myFile:= pFile ^; //应该编译

如果在执行TfrmMain.SaveMsg之后需要文件引用,请不要使用局部变量。

一个全局变量将起作用,但是必须小心,不要在它仍然具有先前值和所需值的情况下覆盖它。

其他(可能更好)的想法是在堆上分配文件变量:使用New(),然后将指针传递给它。

但是,如果执行此操作,则ExportToFileCallBack() 还应该Dispose()分配的指针。

回叫三遍。

如果您的意思是ExportToFileCallBack()将在您之后3次被调用 只能一次调用TfrmMain.SaveMsg,

这意味着更多麻烦!

如果您是第一次使用Dispose()分配的指针,那么该指针当然将在第二次和第三次不再有效!

本文链接:https://www.f2er.com/3161238.html

大家都在问