Skip to main content
Justin Taylor-Hyper Brew
Community Expert
Community Expert
May 28, 2019
Answered

Convert A_UTF16Char to Standard String

Trying to get the footage path to be used in a stream for my plugin, however running into some trouble converting a A_UTF16Char into a standard string. Was trying conversions with wstring_convert, but this keeps giving me access violation errors. Does anyone have a good system for this? Thanks!

std::string utf16_to_utf8(std::wstring utf16_string)

{

     return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.to_bytes(utf16_string);

}

[...]

AEGP_ItemH layer_itemH = NULL;

AEGP_MemHandle pathH;

AEGP_ItemType item_type;

AEGP_FootageH layer_footageH = NULL;

ERR(suites.LayerSuite7()->AEGP_GetLayerSourceItem(layerH, &layer_itemH));

ERR(suites.ItemSuite6()->AEGP_GetItemType(layer_itemH, &item_type));

ERR(suites.FootageSuite5()->AEGP_GetMainFootageFromItem(layer_itemH, &layer_footageH));

ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));

if (item_type == AEGP_ItemType_FOOTAGE && !err && pathH) {

     std::wstring res16;

     ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16)));

     if (res16.size() > 0) {

          std::string resStr = utf16_to_utf8(res16);

          [...]

     }

     ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(pathH));

}

This topic is closed to new replies. Start a new post to keep the conversation going.
Justin Taylor-Hyper Brew
Community Expert
May 29, 2019

You should lock using the handle, then use the pointer you are given (i.e. copy or convert the content it points to), then unlock/free the handle again.

In your code, you are locking and then freeing and then using the now invalid pointer res16B. This might still work most of the time since the memory the variable points to hasn't been overwritten yet in that short amount of time (probably), but it is a horrendous bug to track down should it happen, believe me. So it is probably best to put the AEGP_FreeMemHandle after all your pointer operations.


Thanks Toby! That may have solved some of the sporadic issues I've been having. I'm seeing mixed uses of UnlockMemHandle() and FreeMemHandle() in the docs and SDK samples, but using both seems to work for now. Here's what's working for me now:

wchar_t* res16B;

AEGP_MemHandle pathH;

ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));

ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));

std::wstring ws(res16B);

std::string resStr(ws.begin(), ws.end());

ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(pathH));

ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));

8 replies

Community Expert
May 29, 2019

you can't lock pathH directly into a std::wstring. you need to lock it into

"A_UTF16Char *tempC";

you must also later delete pathH and not only unlock it.

On Wed, May 29, 2019 at 2:50 AM justintaylor <forums_noreply@adobe.com>

Translate
Justin Taylor-Hyper Brew
Community Expert
Community Expert
May 29, 2019

Yea, wstring wasn't the answer. I ended up using wchar_t since I haven't found any other way of converting A_UTF16Char

std::string UTF16_to_String(wchar_t* utf_string)

{

    std::vector<char> tmp_buff;

    _locale_t        locale = _create_locale(LC_ALL, "en");

    size_t            len;

    {

          _wcstombs_s_l(&len, NULL, 0, utf_string, 0, locale);

          tmp_buff.resize(len + 1);

          _wcstombs_s_l(NULL, &tmp_buff[0], len, utf_string, len, locale);

          if (&tmp_buff[0] == NULL)

              return "";

          else

              return &tmp_buff[0];

    }

}

[...]

wchar_t* res16B;

AEGP_MemHandle pathH;

ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));

ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));

ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));

std::string resStr = UTF16_to_String(res16B);

This is working for now anyway. Only saw examples in the examples of freeing (not unlocking) a memory handle after using it, but you're saying I need to delete pathH as well? I haven't had any memory leak errors with this method yet...

Translate
Justin Taylor-Hyper Brew
Community Expert
Community Expert
May 29, 2019

Actually, _wcstombs was crashing if I changed interpret settings with preview turned on for some reason. Here's a more simplified conversion.

wchar_t* res16B;

AEGP_MemHandle pathH;

ERR(suites.FootageSuite5()->AEGP_GetFootagePath(layer_footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));

ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&res16B)));

ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));

std::wstring ws(res16B);

std::string resStr(ws.begin(), ws.end());

This seems to work pretty well now, but I'm all ears if someone has a more straightforward method.

Translate