6

SomeLib.dllWindowsでは、 Python2.7からC++でプログラムされたサードパーティのDLL()を使用して使用しようとしていますctypes。その機能の一部について、このライブラリは別のCOM DLL(SomeCOMlib.dll)を使用し、それ自体が他のDLL(LibA.dll)を使用します。

これは、Pythonから直接COM DLLを使用することではなく、Pythonからそれを使用するDLLを使用することであることに注意してください。

Pythonとの統合を容易にするために、使用したい呼び出しを新しいDLL()の独自の関数にグループ化しました。これもC ++でプログラムされており、より便利な(特定の関数の使用と調整)MyLib.dllからの呼び出しを簡単に行うことができます。シナリオ)。基本的に、私のライブラリは2つの関数を公開しています: 、(すべて戻り、パラメータなし)。ctypesextern "C"doSomethingSimple()doSomethingWithCOMobj()void

「効果的な」依存関係階層は次のとおりです。

MyLib.dll
  SomeLib.dll
    SomeCOMlib.dll
      LibA.dll

MyLib.dllこれらの2つの連続した呼び出しを問題なく使用および実行する単純なC++コンソールアプリケーション(Visual C ++)を作成できます。

Python / ctypesを使用すると、最初の呼び出しは正常に機能しますが、COMを使用する呼び出しは。をスローしWindowsError: [Error -529697949] Windows Error 0xE06D7363ます。ライブラリの残りの動作から、問題はそのCOM呼び出しが行われた場所で正確に発生することがわかります。

LibA.dll(単純なテストC ++アプリケーションも、欠落している場合は同じ場所で多かれ少なかれ失敗しますが、それが関連しているかどうかはわかりません。)

DependencyWalkerを使用して依存関係の階層を確認しました。 SomeCOMlib.dllSomeLib.dll、明らかに必要ですが、の依存関係としてはリストされていません。また、実行時にも明らかに必要ですが、LibA.dllの依存関係としてはリストされていません。SomeCOMlib.dll

これらのDLLがあるディレクトリ内から、コマンドラインからすべてを実行しています(C ++サンプル実行可能ファイルは正常に動作します)。PATHにそのディレクトリを含めるように強制しようとしました。また、DLLが取得される可能性があると推測したさまざまな場所(C:\Windows\System32およびC:\Python27\DLLs)にDLLをコピーしようとしましたが、成功しませんでした。 SomeCOMlib.dllにも登録されましたregasm.exe

プレーンC++アプリケーションからこのDLLを使用するctypes場合と、COMメカニズムの独自の使用法(および場合によっては他のDLLのその後のロード)に関してPythonとの違いを引き起こす原因は何ですか?

Windows Error 0xE06D7363問題をさらに調査できるようにするために、Pythonよりも少なくとも少し多くの情報を提供するステップはどれですか?

Pythonコードは次のようになります。

import ctypes
myDll = ctypes.WinDLL("MyLib.dll")
myDll.doSomethingSimple()
myDll.doSomethingWithCOMobj() # This statement throws the Windows Error

(にリンクされた、動作するテストC ++スタンドアロンアプリケーションは、MyLib.dll内でまったく同じ呼び出しを行いますmain。)

4

3 に答える 3

5

処理中のCOMオブジェクトが必要な場合は、実装するDLLに直接リンクしないでください。通常はCoCreateInstance/CoCreateInstanceExを使用します。これにより、DLLが読み込まれます。

ルックアップは、アプリケーションのマニフェストとそれに依存するアセンブリマニフェストを通過します。これは、登録不要のCOMをサポートするために行われます。

アプリケーションマニフェストがない場合、または依存するアセンブリマニフェストのいずれもcomClassXML要素でクラスを宣言していない場合、ルックアップはデフォルトでレジストリになります。レジストリは、1という名前のサブキーをチェックし、それ自体にDLLを示すサブキーがあります。HKEY_CLASSES_ROOT\CLSID{<your-CLSID>}InProcServer32

これは、SomeCOMlib.dllが依存関係として表示されない理由を説明しています。おそらく動的にロードされるため、LibA.dllが依存関係として表示されない理由は説明されていません。Dependency Walker内でアプリのプロファイルを作成すると、下部のペインにLoadLibrary呼び出しのログが表示されます。プロファイルを作成するには、Dependency WalkerでPython実行可能ファイルを開き、メニューオプションの[プロファイル]-> [プロファイリングの開始...]に移動し、.pyファイルを実行するパラメーターを設定して、[OK]をクリックします。

0xE06D7363例外コードは、VisualC++例外コードです。のソースコードを確認する必要がありdoSomethingWithCOMobjます。デバッグするには、好みのツール(Visual C ++、WinDbgなど)を使用して、Pythonの実行可能ファイルを開き、.pyファイルを実行するための引数を設定し、アプリケーションを実行する前に関数の最初のステートメントでブレークポイントを有効にします。次に、それを実行し、各命令をステップ実行します。

ネイティブC++アプリケーションとPythonの違いを推測するのは非常に難しいですが、Pythonとで異なるCOM初期化引数が使用されてdoSomethingWithCOMobjいるか、宣言していない__stdcall可能性があります(ただし、重要ではないvoid関数です)。 、またはstdoutに書き込もうとしpythonw.exe、コンソールアプリケーションではないものを使用していることなど。


1.HKEY_CLASSES_ROOTの組み合わせです。HKEY_CURRENT_USER\Software\ClassesHKEY_LOCAL_MACHINE\Software\Classes

于 2012-11-16T20:12:31.870 に答える
2

processexplorerのようなものを使用して、必要なすべてのライブラリが実行中のプロセスにロードされているかどうかを確認できます。

  1. PythonコードのどこかでCOMランタイムを初期化しましたか?あなたのC++コードでは?C++コードとPython/ctypesの違いの1つは、C ++コードでは、dllがロードされるときにdllのDllMain()関数が呼び出されることですが、dllが完全に動的にロードされるため、Python/ctypesはこれを行いません。
于 2012-11-14T17:30:40.133 に答える
1

私はあなたが私が持っていたのと同じ問題を抱えていると推測しますが、この場合とは異なり、私が使用しているdllについて何も知らないので私は本当に知りません。6年経った今でもこれをテストできるかどうかはわかりませんが、インポートpythoncomすることで問題が解決するのではないかと思います。

import ctypes
import pythoncom
myDll = ctypes.WinDLL("MyLib.dll")
myDll.doSomethingSimple()
myDll.doSomethingWithCOMobj() # This statement throws the Windows Error
于 2018-03-14T01:47:23.900 に答える