これは、私が持っていた他の質問に関連しており、回答がありませんでした... libclangへのPython バインディングの内部で何が起こっているのかを理解しようとしていますが、そうするのに本当に苦労しています。
clang/cindex.py の CachedProperty クラスがどのように機能するかを理解するために、 Python と Python のdecorators
両方に関する大量の記事を読みましたが、それでもすべてをまとめることはできません。descriptors
私が見た中で最も関連性の高いテキストは1 つの SO answerであり、このコード レシピは ActiveState にあります。これは少し役に立ちますが、前述したように、まだそこにはいません。
それでは、本題に移りましょう。なぜAssertionError
CIndex を作成しようとしているのかを理解したいのです。関連するコードのみをここに投稿します (cindex.py は 3646 行の長さです..)。私のコードには、関連する行が 1 つしかありません。
index = clang.cindex.Index.create()
これは cindex.py の 2291 行を参照しており、次の結果が得られます。
return Index(conf.lib.clang_createIndex(excludeDecls, 0))
これからは、一連の関数呼び出しがありますが、その理由を説明することはできません。pdb
各部分に関連する質問に沿って、コードと出力をリストします。
(事前に注意すべき重要なこと: conf.lib は次のように定義されています:)
class Config:
...snip..
@CachedProperty
def lib(self):
lib = self.get_cindex_library()
...
return lib
CachedProperty コード:
class CachedProperty(object):
"""Decorator that lazy-loads the value of a property.
The first time the property is accessed, the original property function is
executed. The value it returns is set as the new value of that instance's
property, replacing the original method.
"""
def __init__(self, wrapped):
self.wrapped = wrapped
try:
self.__doc__ = wrapped.__doc__
except:
pass
def __get__(self, instance, instance_type=None):
if instance is None:
return self
value = self.wrapped(instance)
setattr(instance, self.wrapped.__name__, value)
return value
Pdb
出力:
-> return Index(conf.lib.clang_createIndex(excludeDecls, 0))
(Pdb) s
--Call--
> d:\project\clang\cindex.py(137)__get__()
-> def __get__(self, instance, instance_type=None):
(Pdb) p self
<clang.cindex.CachedProperty object at 0x00000000027982E8>
(Pdb) p self.wrapped
<function Config.lib at 0x0000000002793598>
- 次の呼び出し
Index(conf.lib.clang_createIndex(excludeDecls, 0))
がCachedProperty.__get__
メソッドになるのはなぜですか? はどう__init__
ですか? - メソッドが呼び出されない場合、
__init__
どうして self.wrapped に価値があるのでしょうか?
Pdb
出力:
(Pdb) r
--Return--
> d:\project\clang\cindex.py(144)__get__()-><CDLL 'libcla... at 0x27a1cc0>
-> return value
(Pdb) n
--Call--
> c:\program files\python35\lib\ctypes\__init__.py(357)__getattr__()
-> def __getattr__(self, name):
(Pdb) r
--Return--
> c:\program files\python35\lib\ctypes\__init__.py(362)__getattr__()-><_FuncPtr obj...000000296B458>
-> return func
(Pdb)
- 値をどこ
CachedProperty.__get__
に返す必要がありますか?CDLL.__getattr__
メソッドの呼び出しはどこから来たのですか?
私にとって最も重要な部分
(Pdb) n
--Call--
> d:\project\clang\cindex.py(1970)__init__()
-> def __init__(self, obj):
(Pdb) p obj
40998256
これは、クラス Index が継承するの作成です。ClangObject
- しかし -
__init__
1 つのパラメーターでの呼び出しはどこにありますか? これはconf.lib.clang_createIndex(excludeDecls, 0)
戻ってきたものですか? - この番号 (40998256) はどこから来たのですか? 何度も同じ数字が出ます。私が理解している限り、それは単なる数字である必要がありますが、それが
clang.cindex.LP_c_void_p object
アサーションが失敗した理由です。
要約すると、私にとって最善の方法は、ここでの関数呼び出しのステップバイステップのガイダンスです。