6

以下は、DLL に常駐する C 関数のプロトタイプです。

extern "C" void__stdcall__declspec(dllexport) ReturnPulse(double*,double*,double*,double*,double*);

別のスレッドで、この関数に必要な引数を適切に作成して送信する方法について質問しました。

スレッドは次のとおり です。この C 関数を複数の引数で ctypes でラップするにはどうすればよいですか?

したがって、上記のスレッドの適切な情報を使用しましたが、次のエラーが発生します: WindowsError: 例外: アクセス違反書き込み 0x00001001

どのように進めたらよいか迷っています。Windows XP を使用しています。管理者アカウントでログインすると、問題は解決しますか? それとも、これは Python のメモリ オブジェクトが不変であることに問題がありますか?

皆さんありがとう!

関連する Python で編集:

FROGPCGPMonitorDLL = windll.LoadLibrary('C:\Program Files\MesaPhotonics\VideoFROG 7.0\PCGPMonitor.dll')

#Function argument:double* pulse
sizePULSE = 2 ##Manual is super unclear here
pulse = c_double * sizePULSE
ptrpulse = pulse()

#Function argument:double* tdl
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE == 0 :
    sizeTRACE = 1 #Manually set size to 1 for testing purposes
    print "Size of FROG trace is zero. Probably not right."
tdl = c_double*sizeTRACE
ptrtdl = tdl()


#Function argument:double* tdP
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE==0:
    sizeTRACE=1
    print "Size of FROG trace is zero. Probably not right."
tdP = c_double*sizeTRACE
ptrtdP = tdP()


#Function Argument:double* fdl
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE==0:
    sizeTRACE=1
    print "Size of FROG trace is zero. Probably not right."
fdl = c_double*sizeTRACE
ptrfdl = fdl()

#Function Argument: double* fdP
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE==0:
    sizeTRACE=1
    print "Size of FROG trace is zero. Probably not right."
fdP = c_double*sizeTRACE
ptrfdP = fdP()

FROGPCGPMonitorDLL.ReturnPulse(ptrpulse, ptrtdl, ptrtdP,ptrfdl,ptrfdP)

関連するコードを追加するために編集しました!デバイスの各機能を最初に動作させるための簡単なスクリプトを書いているだけです。変数 sizeTRACE は再利用できますが、現在はテスト コードであり、デバイスが接続されていないため、GetSize() はゼロを返しています。ゼロを掛けるとバズが消えてしまうので、今のところ強制的に 1 にしています。これが明確でない場合は、お詫びし、この投稿を編集しようとします。

2番目の編集:デバイスを接続して、それが役立つかどうかを確認することが提案されました. FROG を接続したばかりですが、まだ同じエラーが発生します。非常に奇妙で、私はかなり無知です。いずれにせよ、ありがとうございました!

4

2 に答える 2

13

表示されるエラーは、管理者権限とは関係ありません。問題は、C を使用していて、不注意で不正な操作を実行していることです (このような操作をチェックしないと、おそらくシステムがクラッシュする可能性があります)。

表示されるエラーは、プログラムがメモリ アドレス 1001 に書き込もうとしているが、そのメモリ アドレスに書き込む必要がないことを示しています。

これは、さまざまな理由で発生する可能性があります。

考えられる理由の 1 つは、ReturnPulse に渡す double* が、ReturnPulse が期待するほど大きくないことです。おそらく、少なくとも GetSize を適切に動作させる必要があります... GetSize を呼び出す代わりに、非常に大きな配列を割り当てるだけで回避できる場合があります。すなわち

ptrfdP = (c_double*100000)()

これにより、100,000 個の double が割り当てられます。これは、デジタル パルスのキャプチャにより適している可能性があります。

もう 1 つの問題は、型変換が期待どおりに行われない可能性があることです。

ReturnPulse が 5 つの double ポインターを受け取ることを ctypes が知っていれば、運が良くなるかもしれません。すなわち

# sometime before calling ReturnPulse
FROGPCGPMonitorDLL.ReturnPulse.argtypes = [POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double)]

これらの手法のいずれも機能しない場合は、使用目的のドキュメントを ReturnPulse で送信してください。

または、C で動作するはずのサンプル コードを送っていただければ、ctypes の同等の実装に翻訳します。

編集: ReturnPulse と ctypes の使用の実装例を追加します。

ReturnPulse が C DLL で実行すると予想されるようなものを実装しました。

void ReturnPulse(double *a, double*b,double*c,double*d,double*e)
{
    // write some values to the memory pointed-to by a-e
    // a-e should have enough memory allocated for the loop
    for(int i = 0; i < 20; i++)
    {
        a[i] = 1.0*i;
        b[i] = 3.0*i;
        c[i] = 5.0*i;
        d[i] = 7.0*i;
        e[i] = 13.0*i;
    }
}

これを DLL (examlib と呼びます) にコンパイルし、次のコードで ctypes を使用して呼び出します。

LP_c_double = ctypes.POINTER(ctypes.c_double)
examlib.ReturnPulse.argtypes = [LP_c_double, LP_c_double, LP_c_double, LP_c_double, LP_c_double, ]

a = (ctypes.c_double*20)()
b = (ctypes.c_double*20)()
c = (ctypes.c_double*20)()
d = (ctypes.c_double*20)()
e = (ctypes.c_double*20)()

examlib.ReturnPulse(a,b,c,d,e)

print 'values are'
for array in (a,b,c,d,e):
    print '\t'.join(map(str, array[:5]))

結果の出力は次のとおりです。

values are
0.0     1.0     2.0     3.0     4.0
0.0     3.0     6.0     9.0     12.0
0.0     5.0     10.0    15.0    20.0
0.0     7.0     14.0    21.0    28.0
0.0     13.0    26.0    39.0    52.0

実際、ReturnPulse.argtypes を設定しなくても、コードはエラーなしで実行されます。

于 2009-09-10T03:18:18.723 に答える
0

ptrpulse とその仲間は、さまざまな ctypes オブジェクトを指す python 識別子です (それらはすべて c_double*2 だと思います)。ctypes ポインタ オブジェクトでラップするか、ctypes.byref を使用して C 関数に渡す必要があります。

于 2010-01-19T14:13:07.250 に答える