web-dev-qa-db-ja.com

Python Ctypesを使用してdllをロードする

ここに示した例を見てきました ctypes-Beginner そして同じ手順を別のCコードで実行しました。ここに示すCコードを使用して.dllと.libを作成しました: http://wolfprojects.altervista.org/articles/dll-in-c-for-python/

  //test.c
__declspec(dllexport) int sum(int a, int b) {
    return a + b;
}

私のwrapper.pyにはこれがあります:

import ctypes

testlib = ctypes.CDLL("C:\\Users\\xyz\\Documents\\Python\\test.dll")

スクリプトを実行すると、次のエラーが発生します。

self._handle = _dlopen(self._name、mode)

OSError:[WinError 193]%1は有効なWin32アプリケーションではありません

使用する場合

testlib = ctypes.LibraryLoader("C:\\Users\\xyz\\Documents\\Python\\test.dll")

その後、スクリプトの実行時にエラーは発生しません。しかし、私がこれをやろうとすると:

testlib.sum(3,4)

エラーが発生します:

dll = self._dlltype(name)

TypeError: 'str'オブジェクトは呼び出せません

Dllと.pyは同じフォルダーにあります。誰かが私がここで何が起こっているのか理解するのを手伝ってくれますか?私はこれを理解しようと何時間も費やしましたが、壁にぶつかりました。ありがとう。

5
kronosjt

コンパイラとバージョンのPythonが両方とも32ビットまたは両方が64ビットであることを確認してください。混合することはできません。これがOSError: [WinError 193] %1 is not a valid Win32 applicationの原因です。

次に、C++ではなくCプログラムとしてコンパイルするようにしてください。それがあなたの答えの中で名前マングリングの言及の原因です。

例(コンパイラはx86ではなくx64用であることに注意してください:

C:\>cl /LD /W4 test.c
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.61030 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.dll
/dll
/implib:test.lib
test.obj
   Creating library test.lib and object test.exp

2ビット Pythonを使用します:

C:\>py -2
Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> lib = CDLL('test')
>>> lib.sum(2,3)
5

C++としてコンパイルする場合でも、関数をCとしてエクスポートすることで関数を呼び出すことができます。これにより、C++の名前マングリングが防止されます。

//test.cpp
extern "C" __declspec(dllexport) int sum(int a, int b) {
    return a + b;
}
5
Mark Tolonen

さらに掘り下げた後、私は解決策を見つけました。 Cコンパイラが関数の名前を壊してしまったため、sumメソッドを呼び出すときに属性エラーが発生しました。 link.exeを使用してマングルされた名前を特定し、getattrメソッドを使用する必要がありました。

この投稿の詳細と説明: Python:ctypesを使用したDLL関数へのアクセス-関数*名*によるアクセスは失敗します

0
kronosjt