Index: bindings/python/clang/cindex.py =================================================================== --- bindings/python/clang/cindex.py +++ bindings/python/clang/cindex.py @@ -73,6 +73,30 @@ # this by marshalling object arguments as void**. c_object_p = POINTER(c_void_p) +# Python 3 strings are unicode, translate them to/from utf8 for C-interop +if type(u"") == str: + class c_string_p(c_char_p): + def __init__(self, p=None): + if p is None: + p = "" + if type(p) == str: + p = p.encode("utf8") + super(c_char_p, self).__init__(p) + + def __str__(self): + return self.value + + @property + def value(self): + return super(c_char_p, self).value.decode("utf8") + + @classmethod + def from_param(cls, param): + return cls(param) +else: + c_string_p = c_char_p + + callbacks = {} ### Exception Classes ### @@ -147,7 +171,7 @@ class _CXString(Structure): """Helper for transforming CXString results.""" - _fields_ = [("spelling", c_char_p), ("free", c_int)] + _fields_ = [("spelling", c_string_p), ("free", c_int)] def __del__(self): conf.lib.clang_disposeString(self) @@ -554,8 +578,8 @@ if value >= len(self.__class__._kinds): self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1) if self.__class__._kinds[value] is not None: - raise ValueError,'{0} value {1} already loaded'.format( - str(self.__class__), value) + raise ValueError('{0} value {1} already loaded'.format( + str(self.__class__), value)) self.value = value self.__class__._kinds[value] = self self.__class__._name_map = None @@ -577,7 +601,7 @@ @classmethod def from_id(cls, id): if id >= len(cls._kinds) or cls._kinds[id] is None: - raise ValueError,'Unknown template argument kind %d' % id + raise ValueError('Unknown template argument kind %d' % id) return cls._kinds[id] def __repr__(self): @@ -1775,7 +1799,7 @@ if value >= len(StorageClass._kinds): StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1) if StorageClass._kinds[value] is not None: - raise ValueError,'StorageClass already loaded' + raise ValueError('StorageClass already loaded') self.value = value StorageClass._kinds[value] = self StorageClass._name_map = None @@ -1796,7 +1820,7 @@ @staticmethod def from_id(id): if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]: - raise ValueError,'Unknown storage class %d' % id + raise ValueError('Unknown storage class %d' % id) return StorageClass._kinds[id] def __repr__(self): @@ -2125,7 +2149,7 @@ """ Retrieve the offset of a field in the record. """ - return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname)) + return conf.lib.clang_Type_getOffsetOf(self, c_string_p(fieldname)) def get_ref_qualifier(self): """ @@ -2184,7 +2208,7 @@ class _CXUnsavedFile(Structure): """Helper for passing unsaved file arguments.""" - _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)] + _fields_ = [("name", c_string_p), ("contents", c_string_p), ('length', c_ulong)] # Functions calls through the python interface are rather slow. Fortunately, # for most symboles, we do not need to perform a function call. Their spelling @@ -2539,7 +2563,9 @@ args_array = None if len(args) > 0: - args_array = (c_char_p * len(args))(* args) + args_array = (c_string_p * len(args))() + for i,a in enumerate(args): + args_array[i] = c_string_p(a) unsaved_array = None if len(unsaved_files) > 0: @@ -2548,8 +2574,8 @@ if hasattr(contents, "read"): contents = contents.read() - unsaved_array[i].name = name - unsaved_array[i].contents = contents + unsaved_array[i].name = c_string_p(name) + unsaved_array[i].contents = c_string_p(contents) unsaved_array[i].length = len(contents) ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array, @@ -2727,9 +2753,9 @@ # FIXME: It would be great to support an efficient version # of this, one day. value = value.read() - print value + print(value) if not isinstance(value, str): - raise TypeError,'Unexpected unsaved file contents.' + raise TypeError('Unexpected unsaved file contents.') unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) @@ -2791,9 +2817,9 @@ # FIXME: It would be great to support an efficient version # of this, one day. value = value.read() - print value + print(value) if not isinstance(value, str): - raise TypeError,'Unexpected unsaved file contents.' + raise TypeError('Unexpected unsaved file contents.') unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) @@ -3061,7 +3087,7 @@ [c_object_p]), ("clang_CompilationDatabase_fromDirectory", - [c_char_p, POINTER(c_uint)], + [c_string_p, POINTER(c_uint)], c_object_p, CompilationDatabase.from_result), @@ -3071,7 +3097,7 @@ CompileCommands.from_result), ("clang_CompilationDatabase_getCompileCommands", - [c_object_p, c_char_p], + [c_object_p, c_string_p], c_object_p, CompileCommands.from_result), @@ -3106,7 +3132,7 @@ c_uint), ("clang_codeCompleteAt", - [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int], + [TranslationUnit, c_string_p, c_int, c_int, c_void_p, c_int, c_int], POINTER(CCRStructure)), ("clang_codeCompleteGetDiagnostic", @@ -3122,7 +3148,7 @@ c_object_p), ("clang_createTranslationUnit", - [Index, c_char_p], + [Index, c_string_p], c_object_p), ("clang_CXXConstructor_isConvertingConstructor", @@ -3272,7 +3298,7 @@ ("clang_getCString", [_CXString], - c_char_p), + c_string_p), ("clang_getCursor", [TranslationUnit, SourceLocation], @@ -3419,7 +3445,7 @@ Type.from_result), ("clang_getFile", - [TranslationUnit, c_char_p], + [TranslationUnit, c_string_p], c_object_p), ("clang_getFileName", @@ -3548,7 +3574,7 @@ ("clang_getTUResourceUsageName", [c_uint], - c_char_p), + c_string_p), ("clang_getTypeDeclaration", [Type], @@ -3643,7 +3669,7 @@ bool), ("clang_parseTranslationUnit", - [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int], + [Index, c_string_p, c_void_p, c_int, c_void_p, c_int, c_int], c_object_p), ("clang_reparseTranslationUnit", @@ -3651,7 +3677,7 @@ c_int), ("clang_saveTranslationUnit", - [TranslationUnit, c_char_p, c_uint], + [TranslationUnit, c_string_p, c_uint], c_int), ("clang_tokenize", @@ -3723,7 +3749,7 @@ Type.from_result), ("clang_Type_getOffsetOf", - [Type, c_char_p], + [Type, c_string_p], c_longlong), ("clang_Type_getSizeOf", @@ -3782,7 +3808,8 @@ def register(item): return register_function(lib, item, ignore_errors) - map(register, functionList) + for f in functionList: + register(f) class Config: library_path = None