一つのC言語のソースで用意する必要が生じだ。
後にも先にもこれ一回限りな気がするけど一応メモ
検証環境は、
Windows 7 64bit版 C Compiler: gcc ライブラリを使う言語とコンパイラ Delphi XE2
Linux (RHEL) C Compiler: gcc ライブラリを使う言語とコンパイラ Fortran 90 pgfortran
まずは、ヘッダファイルとソース
add.h
#ifndef ADD_H
#define ADD_H
int add_(int *a, int *b)
int devide_(float *a, float *b, float *c)
#endif
add.c
#include<stdio.h>
int add_(int *a, int *b){
int c;
c = *a + *b;
return c;
}
int devide_(float *a, float *b, float *c){
*c = *a / *b;
return 0;
}
ポイントは、引数がすべて参照渡しになっている点です。 Fortranが参照渡しがデフォルトなためです。 また、関数名がアンダースコアで終わっているのは、また後で。。。
お次は、コンパイル
まずは、Windowsで
gcc -shared -m32 -o add.dll add.c
-m32 は、32bi tPEバイナリを出力するためのオプションでdllを使う、アプリケーション(exe)が32bitであるため。
次に、Linuxで
gcc -fPIC -shared -o libadd.so add.c
-fPICは、位置独立コード(Position Independent Code)というメモリのどのアドレにもロード可能にするためのオプションです。
そして、使う側。
まずは、Delphi
unit use; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm6 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; TAdd = function(a : PInteger; b : PInteger) : integer ; stdcall; TDevide = function(a : PSingle; b : PSingle; c : PSingle) : integer ; stdcall; var Form6: TForm6; implementation {$R *.dfm} procedure TForm6.Button1Click(Sender: TObject); var ret : integer; a,b : integer; c,d,e : single; Handle : THandle; Add : TAdd; Devide : TDevide; begin a := 4; b := 2; c := 4.0; d := 2.0; Handle := LoadLibrary('add.dll'); if Handle <> 0 then begin @Add := GetProcAddress(Handle, 'add_'); if @Add <> nil then begin ret := add(@a, @b); ShowMessage(IntToStr(ret)); end; @Devide := GetProcAddress(Handle, 'devide_'); if @Devide <> nil then begin ret := devide(@c, @d, @e); ShowMessage(FloatToStr(e)); end; FreeLibrary(Handle); end; end; end.
関数をtypedefして、GetProcAddress にて関数のあるアドレスを取得する。
次は、Linux上のFortran
interface節を記述したインクルードファイルを作成
addf.h
interface
integer function add(a,b)
integer a,b
end function add
integer function devide(a,b,c)
real a,b,c
end function devide
end interface
次にFortranのソース本体
program test
include 'addf.h'
integer c,d
real e,f,g
c=4
d=2
e=4.0
f=2.0
d = add(c,d)
i = devide(e,f,g)
write(*,*) d,g,i
end program test
そしてコンパイル
pgfortran -I./include -L./lib -ladd src/use.f
-l で使用するライブラリを指定します。
また、Fortranの場合、関数名は、アンダースコアがついたシンボルを探すのでCの関数名には、アンダースコアをつける必要があります。
0 件のコメント:
コメントを投稿