Контейнеры здесь не при чем.
Все дело в том, что входной параметр функции в 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