Выделите несколько структур в памяти

Мне нужно передать несколько значений в память, мне нужно сделать различные страны в CEN / XFS.

Это API: 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();
}
}

0

Решение

Я думаю, что вы пытаетесь обработать сообщение 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 много концептуальных вещей описано. О конфигурации, управлении памятью и так далее.

0

Другие решения

Ваш код выглядит очень надёжно.

Идиоматический способ сделать это в C ++ будет:

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

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

Обновить:

Я только что заметил, что вы, видимо, взаимодействуете с API в стиле c и используете его 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];
3

Объявите массив:

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, если вы делаете, и, вероятно, было бы не очень хорошая идея, чтобы передать std::string через границу DLL.

1

Вы можете вызвать malloc для выделения нескольких структур, если они являются так называемыми POD — обычными старыми данными — или структурами без деструкторов, функций-членов или классов-членов с этими характеристиками.

Однако единственная причина для этого — быть совместимым с C или писать код очень низкого уровня.

Как правило, вы хотите создать std :: vector. Вектор обрабатывает всю память за вас, и вы можете push_back столько членов, сколько вам нужно. Используйте резерв (или измените размер), если важна эффективность. Есть также член с именем data (), который существует для совместимости с C (однако C не может вызвать ваш вектор, по крайней мере, не легко).

0

Ваш код продолжает выдавать WFS_ERR_INTERNAL_ERROR, потому что у вас нет полностью функциональной настройки среды XFS, настроена правильная конфигурация или эмулируйте ее (ключи реестра, sdk, dll и т. д.), а затем протестируйте ее снова, убедитесь, что ваш код содержит правильные заголовки и уверен, что вы ссылаетесь на msxfs.lib, xfs_conf.lib и xfs_supp.lib

0