C++ 正在寻找将std::wstring与NSLog一起使用的最便宜的方法
我有一个广泛使用wstring的库。我需要使用NSLog输出更改和外部数据。是否有一种简单的方法(不太昂贵)使用中间函数输出wstring。 使用va_list将每个wstring转换为NSString是我现在能想到的唯一方法C++ 正在寻找将std::wstring与NSLog一起使用的最便宜的方法,c++,objective-c,std,nslog,wstring,C++,Objective C,Std,Nslog,Wstring,我有一个广泛使用wstring的库。我需要使用NSLog输出更改和外部数据。是否有一种简单的方法(不太昂贵)使用中间函数输出wstring。 使用va_list将每个wstring转换为NSString是我现在能想到的唯一方法 编辑:更精确。我有一个多平台库。我添加了一个日志宏MYLog 编辑 我必须用C++调用我的MYLog,在那个时候我没有访问ObjtoC的权限。所以问题是,在调用MYLog之前,我无法转换std::wstring 通过MYLog,我希望能够使用NSLog或类似以下的中
编辑:更精确。我有一个多平台库。我添加了一个日志宏MYLog
编辑 我必须用C++调用我的MYLog,在那个时候我没有访问ObjtoC的权限。所以问题是,在调用MYLog之前,我无法转换std::wstring
通过MYLog,我希望能够使用NSLog或类似以下的中间版本:
MYLog("Received %ls(%d) from user %ls %ls cp: %ls /nRAW:/t%ls",
&d.name, d.id, &d.user.firstName, &d.user.lastName,
&d.caption, &d.rawText);
(最初来自)我发现NSString中添加了以下内容:
@interface NSString (cppstring_additions)
+(NSString*) stringWithwstring:(const std::wstring&)string;
+(NSString*) stringWithstring:(const std::string&)string;
-(std::wstring) getwstring;
-(std::string) getstring;
@end
@implementation NSString (cppstring_additions)
#if TARGET_RT_BIG_ENDIAN
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32BE);
#else
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32LE);
#endif
+(NSString*) stringWithwstring:(const std::wstring&)ws
{
char* data = (char*)ws.data();
unsigned size = ws.size() * sizeof(wchar_t);
NSString* result = [[NSString alloc] initWithBytes:data length:size encoding:kEncoding_wchar_t];
return result;
}
+(NSString*) stringWithstring:(const std::string&)s
{
NSString* result = [[NSString alloc] initWithUTF8String:s.c_str()];
return result;
}
-(std::wstring) getwstring
{
NSData* asData = [self dataUsingEncoding:kEncoding_wchar_t];
return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
-(std::string) getstring
{
return [self UTF8String];
}
@end
在不浪费太多时间的情况下,我所能想到的就是创建一个由MYLog调用的中间函数:
#define LAD(data) [logString appendFormat:[NSString stringWithFormat:@"%%%@", c], data]
#define LAP(type) LAD(va_arg(listPointer, type))
void MyLogImplementation(NSString* message, ...)
{
NSMutableString* logString = [[NSMutableString alloc] init];
va_list listPointer;
va_start(listPointer, message);
NSArray* lmc = [message componentsSeparatedByString:@"%"];
int counter = 0;
//NSLog(@"there are %d components in %@.", [lmc count], message);
BOOL ignoreNext = NO;
for (NSString* c in lmc)
{
//NSLog(@"Testing %@", c);
if (ignoreNext)
{
[logString appendFormat:@"%%%@", c];
ignoreNext = NO;
}
if (0 == [c length])
{
ignoreNext = !ignoreNext;
}
else if (0 == counter && '%' != [message characterAtIndex:0] )
{
[logString appendFormat:@"%@", c];
}
else
{
switch ([c characterAtIndex:0])
{
case 'd':
case 'i':
LAP(int);
break;
case 'X':
case 'x':
LAP(int);
break;
case '@':
LAP(NSObject*);
break;
case 'f':
LAP(double);
break;
case 'c':
LAP(char);
break;
case 'l':
switch ([c characterAtIndex:1])
{
case 's':
{
std::wstring* str = va_arg(listPointer, std::wstring*);
NSString* nstr = [NSString stringWithwstring:str];
[logString appendFormat:@"%@", nstr];
[nstr release];
if (2 < [c length])
{
[logString appendString:[c substringFromIndex:2]];
}
}
break;
}
break;
default:
[logString appendFormat:[NSString stringWithFormat:@"%%%@", c]];
}
}
++counter;
}
NSLog(@"%@", logString);
[logString release];
va_end(listPointer);
}
问题就解决了。但我会失去多重形式的优势。。。我想。您可以将其转换为NSString并记录下来。这是取自的NSString类别。不知道它有多好,但看起来很合理
@interface NSString (wstring_additions)
+(NSString*) stringWithwstring:(const std::wstring&)string;
-(std::wstring) getwstring;
@end
@implementation NSString (wstring_additions)
#if TARGET_RT_BIG_ENDIAN
const NSStringEncoding kEncoding_wchar_t =
CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32BE);
#else
const NSStringEncoding kEncoding_wchar_t =
CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32LE);
#endif
+(NSString*) stringWithwstring:(const std::wstring&)ws
{
char* data = (char*)ws.data();
unsigned size = ws.size() * sizeof(wchar_t);
NSString* result = [[[NSString alloc] initWithBytes:data length:size encoding:kEncoding_wchar_t] autorelease];
return result;
}
-(std::wstring) getwstring
{
NSData* asData = [self dataUsingEncoding:kEncoding_wchar_t];
return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
@end
如果您使用CoreFoundation将其转换为CFStringRef,然后将其传递给CFLog(…)或将其转换为NSString*(免费桥接)并使用NSLog(…) CFStrings位于CoreFoundation中,它是一个C级API,因此应该可以从非objc区域调用
包含CFStringCreateWithBytes(…)
或者CFStringCreateWithCString(…)
并传递相应的CFStringEncoding
您可以填写NSLog的详细信息吗calls@AlfP.Steinbach对我补充了关于这个问题的更多细节。我知道我忽略了最明显的解决方案,隐藏在多平台修辞背后,但我真的很感激能够尽可能多地保持我的应用程序代码不受平台依赖,并尽可能多地隐藏在我的实现层后面。问题是,在大多数地方,我无法访问NSLog和NSString(它主要是C++代码,它应该是跨平台的)我现在要用OSX实现,但是它应该保持跨平台。而且必须处理STD::WSTRY现在是一个负担,直到我找到另一个解决方案为止,我现在称之为MyLoad(BLALABLAH)。它调用一个外部的C++函数,它可以访问目标C。这就是为什么我不能简单地使用<代码> NSCOLL(@“收到%@”,[NSSTRACKWOWSWOST:D.NAME])。我将尽快尝试摆脱wstring…但与此同时,我将尝试您的解决方案。也许使用一些宏,我应该能够摆脱它…我认为您不需要摆脱wstring。如果您可以根据目标有条件地包括(可能在iOS/MacOS上使用#define to flag)然后只包含核心基础头如果设置,然后使用同一个定义上的y.IFDEF,让你的日志记录函数调用CF例程和CFLog(..)调用。如果你用CFSTRIGRIGO……创建它(使用cFrReLee)并检查从创建例程(失败案例)中的空返回,记住释放字符串,这样你就不会崩溃将null传递给CFLAG。(..)或CFRelease(..)。
@interface NSString (wstring_additions)
+(NSString*) stringWithwstring:(const std::wstring&)string;
-(std::wstring) getwstring;
@end
@implementation NSString (wstring_additions)
#if TARGET_RT_BIG_ENDIAN
const NSStringEncoding kEncoding_wchar_t =
CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32BE);
#else
const NSStringEncoding kEncoding_wchar_t =
CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32LE);
#endif
+(NSString*) stringWithwstring:(const std::wstring&)ws
{
char* data = (char*)ws.data();
unsigned size = ws.size() * sizeof(wchar_t);
NSString* result = [[[NSString alloc] initWithBytes:data length:size encoding:kEncoding_wchar_t] autorelease];
return result;
}
-(std::wstring) getwstring
{
NSData* asData = [self dataUsingEncoding:kEncoding_wchar_t];
return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
@end