将CFStringRef转换为char *

21
我正在使用CFDictionaryGetValueCFDictionaryRef 中获取一个 CFStringRef
我一直在尝试使用 CFStringGetCStringCFStringGetCStringPtrCFStringRef 转换为 char* ,但它们要么返回 NULL,要么崩溃。
有没有办法做到这一点?如何做?
谢谢。
编辑:样例代码:
SecStaticCodeRef staticCode;
CFDictionaryRef information;
SecCSFlags flags = kSecCSInternalInformation
            | kSecCSSigningInformation
            | kSecCSRequirementInformation
            | kSecCSInternalInformation;    
CFURLRef pathURL = NULL;
CFStringRef pathStr = NULL;
CFStringRef uniqueid;
char* str = NULL;
CFIndex length;


pathStr = CFStringCreateWithCString(kCFAllocatorDefault,  
                                    filename, kCFStringEncodingUTF8);    
pathURL = CFURLCreateWithString(kCFAllocatorDefault, pathStr, NULL);
SecStaticCodeCreateWithPath(pathURL, kSecCSDefaultFlags, &staticCode);
SecCodeCopySigningInformation(staticCode, flags, &information);      

uniqueid = (CFStringRef) CFDictionaryGetValue(information, kSecCodeInfoUnique);

// how do I convert it here to char *?
length = CFStringGetLength(uniqueid);
str = (char *)malloc( length + 1 );
CFStringGetCString(uniqueid, str, length, kCFStringEncodingUTF8);

printf("hash of signature is %s\n", str);

CFRelease(information);
CFRelease(staticCode);

1
你的 CFStringGetCString() 崩溃代码是什么样子的?你有查看过这个指南吗? - Georg Fritzsche
我的意思是你正在使用这个代码的地方。 - Georg Fritzsche
请检查问题,我添加了代码。 - Mr Aleph
意思是?我可以在Objective-C上运行它,然后返回我要找的字符串。无论如何,我都在初始化它。 - Mr Aleph
值得一提的是,如果您正在使用 __Objective-C__,您可以使用 __bridge NSString* 强制转换,NSString* ns = (__bridge NSString*)cfStr ; char* regStr=[ns UTF8String] ); - bobobobo
显示剩余3条评论
6个回答

30

这段内容来自iOS:PTL第17章的example code

char * MYCFStringCopyUTF8String(CFStringRef aString) {
  if (aString == NULL) {
    return NULL;
  }

  CFIndex length = CFStringGetLength(aString);
  CFIndex maxSize =
  CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
  char *buffer = (char *)malloc(maxSize);
  if (CFStringGetCString(aString, buffer, maxSize,
                         kCFStringEncodingUTF8)) {
    return buffer;
  }
  free(buffer); // If we failed
  return NULL;
}

生成的缓冲区必须始终被释放(这就是为什么名称中包含“Copy”的原因)。链接的示例代码还有一个稍微更快的版本,它使用由您提供的缓冲区。

如何将该值存储到 char * 中? - Mr Aleph
1
NSDataRef 不是字符串,也不是人类可读字符序列。您想将其转换为其他可读的内容吗(但不是原始值)?使用 CFCopyDescription() 可以实现。 - Rob Napier
这让我想起了最初的问题。CFCopyDescription返回CFStringRef类型,那么如何将其转换为char *类型? - Mr Aleph
1
需要进行一处更正。如果CFStringGetCString()失败,则应释放缓冲区。 - Omkar
我强烈怀疑这个答案存在严重缺陷 - CFStringGetMaximumSizeForEncoding() 函数似乎没有包括空终止符,所以在 malloc 时必须执行 maxSize + 1 (编辑:) 并在调用 CFStringGetCString() 时也要这样做。我刚刚因为一些中文字符串而遇到了这个问题。欢迎投票支持此评论 - 让我们降低全球软件崩溃率。 - Sea Coast of Tibet
显示剩余7条评论

17

另一个答案:

const char *cs = CFStringGetCStringPtr( cfString, kCFStringEncodingMacRoman ) ;
puts( cs ) ; // works

我找不到为什么kCFStringEncodingUTF8会返回NULL,但是kCFStringEncodingMacRoman似乎可以正常工作。


实际上,这对我来说返回了nil。<sulk> - Leslie Godwin
1
我知道这个很老了,但是请看这里:https://developer.apple.com/documentation/corefoundation/1542133-cfstringgetcstringptr “一个指向C字符串的指针,如果字符串的内部存储不允许有效地返回,则为NULL。” - netdigger
显然,如果字符串只有0或1个字符,则也会返回NULL。 :| - jdunning

11

同样的问题还有另外一种一行解决方案:

char * myCString =  [(__bridge NSString *)myCfstring UTF8String];

快乐编程 :)


6
为什么不直接使用以下方法: printf("%s\n", CFStringGetCStringPtr(uniqueid, kCFStringEncodingUTF8));

4

非常简单:

CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
const char *path = CFStringGetCStringPtr(cfStrRef, encodingMethod);

1

来自Core Foundation字符串编程指南文档。以下是如何将CFStringRef的内容作为C字符串获取的方法。

我对其进行了修改,这应该可以满足您的需求。

#include <CoreFoundation/CoreFoundation.h>


CFStringRef str;
//Removed CFRange
const char *bytes; //This is where the conversion result will end up.



str = CFSTR("You Want this String!\n"); //Changed this part

bytes = CFStringGetCStringPtr(str, kCFStringEncodingMacRoman);



if (bytes == NULL) 
{
    //Adding in getting the size
    CFIndex stringLengthIndex = CFStringGetLength(str);

    //Converted index (signed long ) to int
    char localBuffer[(int) stringLengthIndex];

    Boolean success;

    success = CFStringGetCString(str, localBuffer, stringLengthIndex, kCFStringEncodingMacRoman);

}
//At this point the "bytes" variable should contain your C string copied from the provided CFStringRef 

4
这些苹果文档误导性极强。上面的代码中有很多错误(而且苹果代码强烈鼓励你犯这些错误)。您的缓冲区过早地超出作用域并丢掉了结果。如果CFStringGetCStringPtr失败,'bytes'指针就不会指向该字符串。CFStringGetCString中的“10”是错误的(至少应该是stringLengthIndex)。对于某些编码,CFStringGetLength可能过短。等等。这不是您的错;正如我所说,苹果代码误导性极强。请查看我的答案和链接的示例代码,以找到正确的方法来完成此操作。 - Rob Napier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接