Convert A_UTF16Char to Standard String

Adobe Community Professional ,
May 28, 2019 May 28, 2019

Copy link to clipboard

Copied

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));

}

TOPICS
SDK

Views

654

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Adobe Community Professional , May 29, 2019 May 29, 2019
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(res16...

Likes

Translate

Translate
Adobe Community Professional ,
May 28, 2019 May 28, 2019

Copy link to clipboard

Copied

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>

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 28, 2019 May 28, 2019

Copy link to clipboard

Copied

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...

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 28, 2019 May 28, 2019

Copy link to clipboard

Copied

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.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 28, 2019 May 28, 2019

Copy link to clipboard

Copied

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.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 29, 2019 May 29, 2019

Copy link to clipboard

Copied

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));

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 29, 2019 May 29, 2019

Copy link to clipboard

Copied

Every AEGP_LockMemHandle all should be paired with an AEGP_UnlockMemHandle call, and every AEGP_NewMemHandle call should have a corresponding AEGP_FreeMemHandle call somewhere further down the line.

However, there are some SDK function calls that implicitly do one of these things, e.g. the AEGP_GetFootagePath() function internally allocates a new handle already using AEGP_NewMemHandle and passes that back to you. It is then your task to call AEGP_FreeMemHandle when you no longer need it!

So, how do you know when you should free a handle and when not? The only way is to look in the SKD manual or directly in the headers. For AEGP_GetFootagePath, it says for example: "Retrieves the footage path. The path is a handle to a NULL-terminated A_UTF16Char string, and must be disposed with AEGP_FreeMemHandle."

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
May 29, 2019 May 29, 2019

Copy link to clipboard

Copied

Got it, thanks for clarifying!

So in this case I do need to use both Unlock and Free since I'm creating a new handle with AEGP_GetFootagePath() (that needs to be freed with AEGP_FreeMemHandle()) and also locking memory with AEGP_LockMemHandle() (that needs to be unlocked with AEGP_UnlockMemHandle()).

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 29, 2019 May 29, 2019

Copy link to clipboard

Copied

LATEST

Correct

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines