8

静的ライブラリの関数にアクセスするための PHP 拡張機能を作成し、PHP を CGI としてビルドしましたが、すべてが機能しているように見えました (何日も作業した後..)

すべてがうまくいったことに興奮した私は、PHP に含まれていたメッセージをデバッグせずに PHP を再コンパイルしました。( php_printf("here111");.... php_printf("sending arguments...");)

その後、機能しなくなりました。静的ライブラリで呼び出している関数は機能します。別の実行可能ファイルから直接呼び出してテストしました。

デバッグ シンボル ( --enable-debug) を使用して PHP をビルドし、gdb である程度デバッグできます。

私はまだ何が間違っているのかを理解するのに苦労しています。lib( diffFst) 内の関数が入力引数を読み取れないようです。

268     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssssssd",
269        &filA, &filA_len,
270        &nomvarA, &nomvarA_len,
271        &filB, &filB_len,
272        &nomvarB, &nomvarB_len,
273        &filO, &filO_len,
274        &newnomvar, &newnomvar_len,
275        &mult
276        ) == FAILURE) {
277         RETURN_LONG(-100);
278     }
279 
280     php_printf("Read arguments:\nfilA: %s, nomvara: %s\nfilB: %s, nomvarB: %s\nfilO: %s, nomvarO: %s\nMult: %0.3f\n",
281        filA,nomvarA, filB,nomvarB, filO,newnomvar, mult);
282 
285     ier = difffst_(filA,nomvarA, filB,nomvarB, filO,newnomvar, mult);

この関数を呼び出すと、php_printf()ステートメントが機能し、正しい値が出力されます。ただし、difffst_関数を呼び出させると、入力変数を読み取ろうとするとセグメンテーション違反が発生します。

diffFst 関数は fortran で書かれています。

  5 function diffFst(filA, nomvara, filB, nomvarb, filO, newnomvar, change, write_tictac, in_verbose) result(ier)
 10     implicit none
 11 

 12     character (len=*), intent(IN) :: filA, filB, filO
 13     character (len=*), intent(IN) :: nomvara, nomvarb, newnomvar
 14 
 16     real, intent(IN) :: change
 17     logical, intent(IN) :: write_tictac
 18 
 19     logical, intent(IN), optional :: in_verbose
 21     logical :: verbose = .false.
 27     integer :: ier
...
117     ier = fstouv(iuna, 'RND')
118     IF (ier < 0) THEN
119         if (verbose) write(stderr,'(2A)') "Could not fstouv FST file ", trim(filA)
120     ELSE
121         nmax = fstnbr(iuna);
122         if (verbose) write(stdout,'(3A,I6,A)') "Succesfully opened ", trim(filA), ' with ', nmax, ' records'
123         allocate(liste(nmax))
124     END IF

具体的には、(デバッガによると) 122 行目で読み取りに失敗しますfilA

理由はわかりませんが、試しました:

  • 関数をサブルーチンにする
  • 関数を fortran 関数にする
  • 関数を「純粋な」関数にする
  • 戻り値を持つ (それが今あるものですier = ..)
  • returnコード内にステートメントがあり、returnステートメントを削除する
  • 標準出力に出力してファイルをログに記録しようとしました

データが正しく渡されていないようです。デバッガでも引数が読めません。

イライラするのは、ある時点でこれが機能したことです.ファイルのアクセス許可、パスなどを確認しました.そして、Fortranラッパー実行可能ファイルから関数を正常に実行できます.

私が見逃しているトリックはありますか?

ありがとう

4

2 に答える 2

2

しばらく時間がかかり、追加のヘルプが必要でした (このような問題)

基本的に、2 つのことを変更する必要がありました。

  • 参照渡しで整数を渡す
  • 文字列を適切に受け入れる

最初は簡単です、単純にier=func(..., &integer_var, ...)

2 つ目は、文字列の長さを渡すことでした。これを行うにはもっと簡単な方法 (\0 を探して文字列の長さを感知する) があったかもしれませんが、うまくいきませんでした。だから、今私は合格します

ier = func(str,strlen,...)

Fortran では、文字列を次のように受け入れます。

character(kind=c_char,len=strlen), intent(IN) :: str

上記の fortran コードへの具体的な変更点は次のとおりです。

11     use, intrinsic :: iso_c_binding
12     use interfaces_rmnutils
13     implicit none
16     integer(kind=c_int), intent(IN) :: len_filA, len_filB, len_filO
17     character (kind=c_char,len=len_filA), intent(IN) :: filA
18     character (kind=c_char,len=len_filB), intent(IN) :: filB
19     character (kind=c_char,len=len_filO), intent(IN) :: filO

それが機能していたときは、文字列を として読み込もうとする前だったに違いありません。(len=*)整数は参照として渡されていたため、基本的にランダムな値になっていました。

他のみんなもありがとう!

于 2013-01-03T04:57:52.573 に答える
1

あなたのプログラムは、スタックを破壊しているようです。スタックの破損は通常、ポインタの不適切な使用に伴います。疑わしい関数呼び出しの直前に注意深くチェックしてください(デバッガーまたは単純なフットプリントを使用して変数の内容を調査してください)。

于 2013-01-08T15:11:33.010 に答える