【问题标题】:Allocate multiple structs in memory在内存中分配多个结构
【发布时间】:2017-02-20 15:39:22
【问题描述】:

我需要将多个值传递到内存,我需要为 CEN/XFS 创建不同的国家/地区。

这个接口:CashDispenser - CDM

结构参考:WFSCDMCURRENCYEXP

我想怎么做:

HRESULT WINAPI WFPGetInfo(HSERVICE hService, DWORD dwCategory, LPVOID lpQueryDetails, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID) {
WFSRESULT * lpWFSResult;
WFSCDMSTATUS CdmStatus;
WFSCDMCAPS CdmCapabilities; 
WFSCDMCASHUNIT CdmCash;
WFSCDMCURRENCYEXP CdmCurrency;
HRESULT result;

result = WFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_ZEROINIT | WFS_MEM_SHARE, (void**)&lpWFSResult); 

    if(result != WFS_SUCCESS){
        return WFS_ERR_INTERNAL_ERROR;
    }

if(dwCategory == WFS_INF_CDM_CURRENCY_EXP){

    const int countCurrencies = 2;

    WFSCDMCURRENCYEXP** ppCdmCurrencies;

    result = WFMAllocateMore(sizeof(WFSCDMCURRENCYEXP*) * (countCurrencies+1), lpWFSResult, (void**)&ppCdmCurrencies);

    lpWFSResult->hService=hService;      
    lpWFSResult->RequestID=ReqID;
    lpWFSResult->u.dwEventID=WFS_INF_CDM_CURRENCY_EXP;
    lpWFSResult->hResult=WFS_SUCCESS;

    result = WFMAllocateMore(sizeof(WFSCDMCURRENCYEXP), lpWFSResult, (void**)&ppCdmCurrencies[0]);

    WFSCDMCURRENCYEXP& cmdCurrency0(*ppCdmCurrencies[0]);
    memcpy(cmdCurrency0.cCurrencyID, "AED", 3);
    cmdCurrency0.sExponent = 0;

    WFSCDMCURRENCYEXP& cmdCurrency1(*ppCdmCurrencies[1]);
    memcpy(cmdCurrency1.cCurrencyID, "AFA", 3);
    cmdCurrency1.sExponent = 0;

    lpWFSResult->lpBuffer = ppCdmCurrencies;
    logFile.close();
}
}

【问题讨论】:

  • CdmCurrency.cCurrencyID[3] = 'ARG'; 没有做你认为的事情。
  • 什么?没有收到价值?
  • ' 用于单个字符或" 用于一系列字符(通常)
  • @MatheusCardozo 你更需要strcpy(CdmCurrency.cCurrencyID,"ARG");之类的东西。
  • @πάνταῥεῖ : strcpy 将复制 四个 个字符(包括尾随的 null),但 .cCurrencyID 只有三个字符长。

标签: c++ dll struct cen-xfs


【解决方案1】:

您的代码看起来非常 C-ish。

在 c++ 中执行此操作的惯用方法是:

struct WFSCDMCURRENCYEXP
{
   std::string     cCurrencyID;
   SHORT           sExponent;
};

std::vector<WFSCDMCURRENCYEXP> CdmCurrencies {
    { "ARG", 3 } ,
    { "EUA", 3 } ,
    // lots more countries
};

更新:

我刚刚注意到您显然与 c 风格的 API 交互,并且可能需要以原始形式使用 struct
尽管在 c++ 中,您仍然可以使用 std::vector 来管理该结构的动态分配的连续数组:

typedef struct _wfs_cdm_currency_exp
{
   CHAR            cCurrencyID[3];
   SHORT           sExponent;
} WFSCDMCURRENCYEXP, * LPWFSCDMCURRENCYEXP;

std::vector<WFSCDMCURRENCYEXP> CdmCurrencies {
    { { 'A', 'R', 'G' }, 3 } , // Note that the cCurrencyID is a non null terminated 
                               // array here
    { { 'E', 'U', 'A' }, 3 } ,
    // lots more countries
};

LPWFSCDMCURRENCYEXP pCdmCurrencies = &CdmCurrencies[0];

【讨论】:

  • 伙计,这个块有一个编译错误:std::vector CdmCurrencies {..... };
  • @MatheusCardozo 具体是什么错误?我已经更新了我的答案。这是compiling demo)。确保您的编译器启用了 c++11。
  • @MatheusCardozo 你也读过那个警告吗?获取最新的编译器或显式启用 c++11。
  • @MatheusCardozo 您使用的是哪个 IDE?您应该将警告中提到的选项之一添加到您的项目 c++ 编译器标志中。
  • @MatheusCardozo 请注意,您还应确保安装最新的 MinGW GCC 版本。 IIRC Dev-C++ 与旧的过时 GCC 版本打包在一起。
【解决方案2】:

声明一个数组:

WFSCDMCURRENCYEXP CdmCurrency[2];
memcpy( CdmCurrency[0].cCurrencyID, "ARG", 3);
CdmCurrency[0].sExponent = 0; 
memcpy( CdmCurrency[1].cCurrencyID, "EUA", 3);
CdmCurrency[1].sExponent = 0;

memcpy(lpWFSResult->lpBuffer, CdmCurrency, 2*sizeof(WFSCDMCURRENCYEXP));
//                                         ^^

别忘了你需要复制更多的内存。

另请注意,我已修复 .cCurrencyID 的设置 - 字符文字(带单引号)只能包含单个字符。要移动多个字符,您需要从字符串调用 memcpy。通常我会建议使用std::string 而不是char [3],但是如果你这样做了,你就不能使用memcpy,而且跨DLL 边界传递std::string 可能不是一个好主意。

【讨论】:

  • 您记得将 sizeof 乘以计数吗? lpWFSResult->lpBuffer 是否指向足够大的缓冲区?它是如何“不起作用”的?
  • 是的,这个缓冲区有大小。但在我的日志中没有滚动任何内容,xfs 忽略了这一点。
【解决方案3】:

我认为您尝试处理 WFS_INF_CDM_CURRENCY_EXP 消息以获取有关 CDM 中货币的信息。

仔细阅读 XFS 规范:

输出参数 LPWFSCDMCURRENCYEXP *lppCurrencyExp;指向以 NULL 结尾的指向 WFSCDMCURRENCYEXP 结构的指针数组的指针

这意味着您必须分配一个指向 WFSCDMCURRENCYEXP 的指针数组,大小为 N+1,并将最后一项设置为 null。

在 CEN/XFS 中,您不能使用标准的 new 或 malloc 进行内存分配。 您需要使用 WFMAllocateBuffer 和 WFMAllocateMore 为返回给调用者的 XFS 结构分配内存。

对于你的任务,你需要这样的东西:

HRESULT WINAPI WFPGetInfo(HSERVICE hService, DWORD dwCategory, LPVOID lpQueryDetails, DWORD dwTimeOut, HWND hWnd, REQUESTID ReqID) {

WFSRESULT * lpWFSResult;
WFSCDMSTATUS CdmStatus;
WFSCDMCAPS CdmCapabilities; 
WFSCDMCASHUNIT CdmCash;
WFSCDMCURRENCYEXP CdmCurrency;
HRESULT result;

result = WFMAllocateBuffer(sizeof(WFSRESULT), WFS_MEM_ZEROINIT | WFS_MEM_SHARE, (void**)&lpWFSResult); 

    if(result != WFS_SUCCESS){
        return WFS_ERR_INTERNAL_ERROR;
    }

if(dwCategory == WFS_INF_CDM_CURRENCY_EXP){

    const int countCurrencies = 2;

    WFSCDMCURRENCYEXP** ppCdmCurrencies;
    result = WFMAllocateBuffer(sizeof(WFSCDMCURRENCYEXP*) * (countCurrencies+1), WFS_MEM_ZEROINIT | WFS_MEM_SHARE, (void**)&ppCdmCurrencies);

    lpWFSResult->hService=hService;      
    lpWFSResult->RequestID=ReqID;
    lpWFSResult->u.dwEventID=WFS_INF_CDM_CURRENCY_EXP;
    lpWFSResult->hResult=WFS_SUCCESS;

    result = WFMAllocateMore(sizeof(WFSCDMCURRENCYEXP), lpWFSResult, (void**)&ppCdmCurrencies[0]);

    WFSCDMCURRENCYEXP& cmdCurrency0(*ppCdmCurrencies[0]);
    memcpy(cmdCurrency0.cCurrencyID, "AED", 3);
    cmdCurrency0.sExponent = 0;

    result = WFMAllocateMore(sizeof(WFSCDMCURRENCYEXP), lpWFSResult, (void**)&ppCdmCurrencies[1]);

    WFSCDMCURRENCYEXP& cmdCurrency1(*ppCdmCurrencies[1]);
    memcpy(cmdCurrency1.cCurrencyID, "AFA", 3);
    cmdCurrency1.sExponent = 0;

    lpWFSResult->lpBuffer = ppCdmCurrencies;
    logFile.close();
    return WFS_SUCCESS;
}
}

使用 XFS 操作并不是那么简单。这是太多复杂的 API 结构,具有不同的分配规则和数据表示。请仔细阅读 XFS 手册。在第一本书ftp://ftp.cen.eu/CWA/CEN/WS-XFS/CWA16926/CWA%2016926-1.pdf 中描述了许多概念性的东西。关于配置、内存管理等。

【讨论】:

  • 伙计,最后,没有必要:memcpy(lpWFSResult->lpBuffer,&CdmCurrency,sizeof(WFSCDMCURRENCYEXP)); ????
  • 是的,没必要。您已经为所有结构分配内存并仅将其地址存储在 lpWFSResult->lpBuffer
  • 嘿家伙,这个错误-15出现了,WFS_ERR_INTERNAL_ERROR..哇上帝。
  • 在此处创建日志,然后发现(2 AllocateMore 中的错误)...见Image Compile
  • 尝试固定代码。我在第二个 WFMAllocateMore 中犯了错误,需要使用 lpWFSResult 作为基地址。
【解决方案4】:

您可以调用 malloc 来分配多个结构,如果它们是所谓的 POD(普通旧数据)或没有析构函数、成员函数或具有这些特征的成员类的结构。

这样做的唯一原因是为了与 C 兼容,或者是为了编写非常低级的代码。

作为一般规则,您希望创建一个 std::vector。向量为您处理所有内存,您可以根据需要 push_back 任意数量的成员。如果效率很重要,请使用保留(或调整大小)。还有一个名为 data() 的成员是为了与 C 兼容(但是 C 不能调用你的向量,至少不容易)。

【讨论】:

    【解决方案5】:

    您的代码不断抛出 WFS_ERR_INTERNAL_ERROR,因为您没有设置功能齐全的 XFS 环境、设置正确的配置或模拟一个(注册表项、sdk、dll 等)然后再次测试,确保您的代码包含正确的标头并确保链接到 msxfs.lib、xfs_conf.lib 和 xfs_supp.lib

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-20
      • 2016-01-27
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多