Berikut ini adalah penggunaan khas pointer fungsi di C. Saya ingin melakukan sesuatu yang serupa di Fortran. Saya punya beberapa ide, tetapi saya ingin tahu apakah ada cara kanonik untuk melakukannya.
Pointer fungsi dan konteks yang dilewatkan oleh pengguna disimpan, lalu dipanggil nanti.
typedef PetscErrorCode (*TSIFunction)(TS,PetscReal,Vec,Vec,Vec,void*);
PetscErrorCode TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx);
Fungsi pengguna dipanggil kembali menggunakan konteks mereka di berbagai waktu kemudian.
Dalam PETSc, mereka juga menggunakan string -> tabel pointer fungsi. Semuanya adalah plugin, sehingga pengguna dapat mendaftarkan implementasi mereka sendiri dan mereka adalah kelas satu.
#define PCGAMG "gamg"
PCRegisterDynamic(PCGAMG ,path,"PCCreate_GAMG",PCCreate_GAMG);
Ini mendaftarkan kreasi rutin dalam "FList", lalu PCSetFromOptions () menawarkan kemampuan untuk memilih metode ini dibandingkan pilihan lainnya. Jika sistem mendukung pemuatan dinamis, Anda dapat melewati dependensi waktu kompilasi pada simbol PCCreate_GAMG dan hanya melewati NULL, maka simbol tersebut akan dicari di perpustakaan bersama saat run time.
Perhatikan bahwa ini satu langkah di luar "pabrik", itu adalah inversi perangkat kontrol yang mirip dengan apa yang Martin Fowler sebut "pelacak layanan".
Catatan: ini muncul dalam korespondensi pribadi saya dengan Jed Brown, di mana ia mengajukan pertanyaan ini kepada saya. Saya memutuskan untuk melakukan outsourcing dan melihat jawaban apa yang bisa diberikan orang.
Ada banyak hal yang saya duga adalah bahasa khusus PETSc dalam pertanyaan Anda (yang saya tidak kenal), jadi mungkin ada kerutan di sini yang saya tidak mengerti, tapi mungkin ini masih berguna untuk membuat Anda mulai.
Pada dasarnya, Anda harus mendefinisikan antarmuka untuk prosedur, dan kemudian Anda bisa meneruskan pointer ke fungsi yang mengikuti antarmuka ini. Kode berikut menunjukkan contoh. Pertama, ada modul yang mendefinisikan antarmuka dan menunjukkan contoh cepat dari sepotong kode yang akan menjalankan rutin yang disediakan oleh pengguna yang mengikuti antarmuka itu. Berikutnya adalah program yang menunjukkan bagaimana pengguna akan menggunakan modul ini dan menentukan fungsi yang akan dieksekusi.
sumber
PROCEDURE(function_template), POINTER :: func
internal.void*
, pengguna akhirnya harus menulis antarmuka untuk fungsi perpustakaan sendiri. Jika Anda menerapkan pustaka di C, ini sudah cukup, tetapi jika Anda menerapkan di Fortran, Anda harus memastikan bahwa kompiler tidak pernah melihat ANTARMUKA "dummy" pustaka pada saat yang sama dengan INTERFACE pengguna.void*
di Fortran adalahtransfer
metode. Lihat di sini untuk contoh penggunaan. 3 pendekatan lain selaintransfer
metode ini adalah "work array", "tipe turunan spesifik, bukanvoid *
" dan menggunakan variabel modul lokal ke modul.transfer
jenis omong kosong (character (len=1), allocatable
) hanya untuk memanggil fungsi.