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

мне нужно передать несколько значений в память, мне нужно сделать разные страны для 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();
}
}

person Matheus Cardozo    schedule 20.02.2017    source источник
comment
CdmCurrency.cCurrencyID[3] = 'ARG'; делает не то, что вы думаете.   -  person πάντα ῥεῖ    schedule 20.02.2017
comment
Какая? Нет полученного значения?   -  person Matheus Cardozo    schedule 20.02.2017
comment
Используйте ' для одного символа или " для последовательности символов (обычно)   -  person doctorlove    schedule 20.02.2017
comment
@MatheusCardozo Вам скорее нужно что-то вроде strcpy(CdmCurrency.cCurrencyID,"ARG");.   -  person πάντα ῥεῖ    schedule 20.02.2017
comment
@πάνταῥεῖ : strcpy скопирует четыре символа (включая конечный нуль), но .cCurrencyID имеет длину всего три символа.   -  person Martin Bonner supports Monica    schedule 20.02.2017
comment
На самом деле, если бы я был OP, я бы сделал .cCurrencyID длиной четыре символа и оставил место для конечного нуля - это даже не увеличит структуру.   -  person Martin Bonner supports Monica    schedule 20.02.2017
comment
@MartinBonner Я знаю, я просто хотел указать, что простое задание здесь не годится.   -  person πάντα ῥεῖ    schedule 20.02.2017


Ответы (5)


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

person Alex.D.Alexeev    schedule 20.02.2017
comment
Дружище, В итоге не надо было: memcpy(lpWFSResult-›lpBuffer,&CdmCurrency,sizeof(WFSCDMCURRENCYEXP)); ???? - person Matheus Cardozo; 20.02.2017
comment
Да, это не обязательно. Вы уже выделили память для всех структур и храните только ее адрес в lpWFSResult-›lpBuffer - person Alex.D.Alexeev; 20.02.2017
comment
Эй, парень, появляется эта ошибка -15, WFS_ERR_INTERNAL_ERROR..боже. - person Matheus Cardozo; 20.02.2017
comment
Создайте журнал здесь и обнаружите (ошибка в 2 AllocateMore)... См. Компиляция изображения - person Matheus Cardozo; 20.02.2017
comment
Попробуйте фиксированный код. Я сделал ошибку во втором WFMallocateMore, нужно использовать lpWFSResult в качестве базового адреса. - person Alex.D.Alexeev; 20.02.2017
comment
Вы используете lpResultBuffer в первом WFMallocateMore, но не объявляете его в области видимости. ???? - person Matheus Cardozo; 20.02.2017
comment
Я написал этот код по памяти и не проверял орфографию. Я только хочу показать основную идею манипулирования памятью XFS. Проверить исправленную версию - person Alex.D.Alexeev; 20.02.2017
comment
ха-ха, хорошо, спасибо, чувак, я бразилец, извини за мой плохой английский, ты мне помог, но не работает.. :( Продолжение с ошибкой -15. - person Matheus Cardozo; 20.02.2017
comment
Когда вы получаете ошибку -15? Можете ли вы показать мне полный код? - person Alex.D.Alexeev; 21.02.2017
comment
Привет, Алекс, ты можешь мне помочь? - person Matheus Cardozo; 22.02.2017
comment
Привет, я просмотрел свой старый проект и нашел некоторые отличия. Я отправлю его вам позже - person Alex.D.Alexeev; 22.02.2017
comment
См. фиксированный пример в моем ответе. Я не могу проверить это в реальной среде XFS, но этот метод использовался в реальном проекте. Если вы продолжаете получать ошибки, пожалуйста, напишите мне, где вы их получили. Я постараюсь помочь вам. P.S. меня не будет до следующего понедельника - person Alex.D.Alexeev; 22.02.2017

Ваш код выглядит очень C-ish.

Идиоматический способ сделать это на С++:

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];
person πάντα ῥεῖ    schedule 20.02.2017
comment
Чувак, у этого блока ошибка компиляции: std::vector‹WFSCDMCURRENCYEXP› CdmCurrencies {..... }; ‹--- - person Matheus Cardozo; 20.02.2017
comment
@MatheusCardozo Какая конкретно ошибка? Я немного обновил свой ответ. Вот демонстрация компиляции). Убедитесь, что c++11 включен в вашем компиляторе. - person πάντα ῥεῖ; 20.02.2017
comment
@MatheusCardozo Значит, вы тоже читали это предупреждение? Получите последний компилятор или явно включите С++ 11. - person πάντα ῥεῖ; 20.02.2017
comment
@MatheusCardozo Какую IDE вы используете? Вы должны добавить одну из опций, упомянутых в предупреждении, к флагам компилятора C++ ваших проектов. - person πάντα ῥεῖ; 20.02.2017
comment
@MatheusCardozo Обратите внимание, что вы также должны установить последнюю версию MinGW GCC. IIRC Dev-C++ поставляется со старой устаревшей версией GCC. - person πάντα ῥεῖ; 20.02.2017
comment
Эй, как эта часть? memcpy(lpWFSResult->lpBuffer,&CdmCurrency,sizeof(WFSCDMCURRENCYEXP)); - person Matheus Cardozo; 20.02.2017
comment
@MatheusCardozo Эй, как тебе эта часть? Зачем тебе это нужно? - person πάντα ῥεῖ; 20.02.2017
comment
@MatheusCardozo Относительно флагов компилятора см. здесь также пожалуйста. (И нет, пожалуйста, не начинайте чат, просто проигнорируйте сообщение). - person πάντα ῥεῖ; 20.02.2017
comment
@MatheusCardozo Вероятно, вы должны уметь писать: lpWFSResult->lpBuffer = pCdmCurrencies; - person πάντα ῥεῖ; 20.02.2017

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

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.

person Martin Bonner supports Monica    schedule 20.02.2017
comment
Вы не забыли умножить sizeof на количество? Указывает ли lpWFSResult->lpBuffer на достаточно большой буфер? Как это не работает? - person Martin Bonner supports Monica; 20.02.2017
comment
Да, этот буфер имеет размер. Но у меня в логе ничего не катится, xfs игнорирует это. - person Matheus Cardozo; 20.02.2017

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

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

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

person Malcolm McLean    schedule 20.02.2017

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

person lucas    schedule 10.05.2017