关闭

UWP中重用C/C++代码时踩过的一些坑

发表于:2016-6-29 09:58

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:MS-UAP    来源:51Testing软件测试网采编

  坑3:命名空间和文件名
  运行时组件创建完成时,根命名空间和工程的名称是一样的,直接使用没有问题。但有的同学希望修改命名空间的名称以符合公司的命名规范,此时,有以下几点需要注意:
  一个是如何修改命名空间,不仅仅要将代码中命名空间修改,还要修改工程的根命名空间,方法是打开属性窗口,单击工程,就可以看到根命名空间。这两处要保持致,否则引用的工程无法编译通过。
  再一个是修改完命名空间后,编译产生的dll和winmd文件名称不同,在按文件添加完引用后,主工程可以编译通过,但是会有APPX1707的警告,并且运行时会发生崩溃。分析后发现,原来是VS默认引用的时候会用winmd文件的名称去找dll文件,而现在两个文件名称不一样,所以会找不到实现。解决方案有两种,一种是修改运行时组件工程选项,使得输出的文件名保持一致;另一种是在主工程添加完winmd文件的引用后,手动编辑一下主工程的工程文件,在引用处加入如下图所示的一行,强制指定对应的实现在哪个dll文件中。
  坑4:字符串转换
  C/C++实现的库中,有相当一部分还是用的std::string,没有使用宽字符,为了保证这种情况下的中文可以正确的传递不出乱码,需要对字符串进行转换。闲话不多说,直接上代码。
// UTF编码的多字节转为宽字符
std::wstring TUtf8ToUnicode(const char * pszUtf8Str, unsigned len = -1)
{
std::wstring ret;
do
{
if (!pszUtf8Str) break;
// get UTF8 string length
if (-1 == len)
{
len = strlen(pszUtf8Str);
}
if (len <= 0) break;
// get UTF16 string length
int wLen = MultiByteToWideChar(CP_UTF8, 0, pszUtf8Str, len, 0, 0);
if (0 == wLen || 0xFFFD == wLen) break;
// convert string
wchar_t * pwszStr = new(std::nothrow) wchar_t[wLen + 1];
if (!pwszStr) break;
pwszStr[wLen] = 0;
MultiByteToWideChar(CP_UTF8, 0, pszUtf8Str, len, pwszStr, wLen + 1);
ret = pwszStr;
delete[] pwszStr;
} while (0);
return ret;
}
// std::string => Platform::String
Platform::String ^ Ts2ps(std::string str)
{
return ref new Platform::String(TUtf8ToUnicode(str.c_str()).c_str());
}
// 宽字符转为UTF8编码的多字节
std::string TUnicodeToUtf8(const wchar_t* pwszStr)
{
std::string ret;
do
{
if (!pwszStr) break;
size_t len = wcslen(pwszStr);
if (len <= 0) break;
size_t convertedChars = 0;
char * pszUtf8Str = new(std::nothrow) char[len * 3 + 1];
if (!pszUtf8Str) break;
WideCharToMultiByte(CP_UTF8, 0, pwszStr, len + 1, pszUtf8Str, len * 3 + 1, 0, 0);
ret = pszUtf8Str;
delete[] pszUtf8Str;
} while (0);
return ret;
}
// Platform::String => std::string
std::string Tps2s(Platform::String ^ pstr)
{
if (pstr == nullptr)
return "";
return TUnicodeToUtf8(pstr->Data());
}
  坑5:数组在异步中怎么传
  如何在接口中使用数组,可以参考 https://msdn.microsoft.com/zh-cn/library/hh700131.aspx 这篇文章。里面提到不同场景下分别用什么样的数组,讲的非常详细,这里就不再重复了,重点扒一下遇到的坑。
  数组作为WinRT接口的返回值时,如果该接口是同步的,一切正常;当接口是异步的时候,编译器就会抛出
  error C3952: 'Platform::Array<int,1> ': WinRT does not support 'in/out' arrays. Use 'const Array<T>^' for 'in' and 'WriteOnlyArray<T>' or 'Array<T>^*' for 'out' on public APIs
  按照该提示进行修改,怎么都不好使,后经过多方求解,才知道这种情况下需要进行装箱操作才可以。示例代码出下:
IAsyncOperation<Platform::Object^>^ GetArrayAsync()
{
return create_async([]() -> Platform::Object^
{
Array<int>^ arr1 = ref new Array<int>(10);
for (int i = 0; i < arr1->Length; i++)
{
arr1[i] = i + 1;
}
Platform::Object^ a = arr1;
return a;
});
}
  以上是我们在开发过程中遇到的一些坑和解决方案,如有理解不当之处,请小伙伴指出来,另外小伙伴们也可以在评论中积极分享下你们遇到过哪些坑,是如何解决的,大家共同进步。
22/2<12
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号