Показать сообщение отдельно
Старый 06.06.2007, 11:04   #6  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2476 (88) +++++++++
Регистрация: 20.08.2005
Контейнеры здесь не при чем.
Все дело в том, что входной параметр функции в dll имеет тип BSTR, а не LPSTR, который вы передаете в нее.
Особенность этого типа (BSTR) в том, что он хранит размер строки (ну и еще - это юникод). Причем, это размер хранится в первых четырех байтах памяти, в которой размещена строка. В функцию передается не начало блока (где хранится размер), а смещение на четыре байта, т.е. указатель на саму строку. За счет этого такой тип можно передавать как обычную юникодную строку.
Если вызываемая функция ожидает в параметре тип BSTR, то она может проверить размер строки, просто обратившись к памяти по смещению -4 от начала стороки (для этого есть специальные функции в OLE API).

Что происходит в вашем случае - вы передаете в качестве параметра обычную строку (тип LPSTR или char * для языка C). Этот тип не предусматривает хранение размера перед сторокой, по-этому при размещении в памяти данные копируются с начального адреса. При этом, блок памяти выделяется системой последовательно после уже размещенного в памяти другого объекта. Если в последнем двойном слове этого объекта не ноль, то проверка на размер для типа BSTR верное какое-то число (конечно, это не размер строки, но проверка обычно идет на !0) и алгоритм отработает, как если бы тип был правильный. Если же 0 - то просто возвращается входная строка.

Ну и на последок - пример рабочего кода
X++:
str  encode(str _string)
{
    DLLFunction         _BC_Code128;
    DLL                 _barcodeDLL;
    str                 barcodeStr;
    ComVariant          var = ComVariant::createFromStr(_string);
;
    try
    {
        _barcodeDLL = new DLL('Bcfont32');
    } catch(Exception::Internal)
    {
        info("barcodeDLL error!!!");
        return '';
    }
    _BC_Code128 = new DLLFunction(_barcodeDLL,'BC_Code128');
    _BC_Code128.returns(ExtTypes::String);
    _BC_Code128.arg(ExtTypes::DWord);
    barcodeStr = _BC_Code128.call(var.int());
    _barcodeDLL = null;
    _BC_Code128 = null;
    return barcodeStr;
}
Кстати, это самый простой способ получения юникода в Axapta 3.0
__________________
Axapta v.3.0 sp5 kr2
За это сообщение автора поблагодарили: EVGL (3), rumpleteazer (1), petr (3), SHiSHok (2), gl00mie (5).