Мне нужно передать несколько значений в память, мне нужно сделать различные страны в 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();
}
}
Я думаю, что вы пытаетесь обработать сообщение 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 много концептуальных вещей описано. О конфигурации, управлении памятью и так далее.
Ваш код выглядит очень надёжно.
Идиоматический способ сделать это в 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];
Объявите массив:
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.
Вы можете вызвать malloc для выделения нескольких структур, если они являются так называемыми POD — обычными старыми данными — или структурами без деструкторов, функций-членов или классов-членов с этими характеристиками.
Однако единственная причина для этого — быть совместимым с C или писать код очень низкого уровня.
Как правило, вы хотите создать std :: vector. Вектор обрабатывает всю память за вас, и вы можете push_back столько членов, сколько вам нужно. Используйте резерв (или измените размер), если важна эффективность. Есть также член с именем data (), который существует для совместимости с C (однако C не может вызвать ваш вектор, по крайней мере, не легко).
Ваш код продолжает выдавать WFS_ERR_INTERNAL_ERROR, потому что у вас нет полностью функциональной настройки среды XFS, настроена правильная конфигурация или эмулируйте ее (ключи реестра, sdk, dll и т. д.), а затем протестируйте ее снова, убедитесь, что ваш код содержит правильные заголовки и уверен, что вы ссылаетесь на msxfs.lib, xfs_conf.lib и xfs_supp.lib