もし,同一のマシンにVisualC/C++(以下VC)とVisual Fortran(以下VF)が両方インストールされて いるのなら,VFでコンパイルしたオブジェクトファイル(.OBJ)および スタティックライブラリ(.LIB)を,VCのプロジェクトに追加し,Cのコードとリンクさせる ことができる.
さらに,VCとVFのバージョンが整合していれば,すなわち,両方とも5.0あるいは6.0ならば, Developer Studioが共用され,一つのプロジェクトにFortranとCのソースコードを混在させることができる.
しかしながら,VCのみの環境では,VFで作成したOBJやLIBを利用することはできない. VFで作成されたOBJおよびLIBは,メインプログラムにリンクされるときに, VFが提供するdfor.lib,dfconsol.lib,dfport.libなどのライブラリを必要とする. これらのスタティックライブラリはCompaq社が再配布を認めていないので,
VFがインストールされていない環境では VFで作成したOBJやLIBを利用することができない
のである. ここにも書いたが, VFのDeveloper Studioで作成したプログラムを実行するには, VFが提供するランタイムライブラリが必要である. こちらの方はCompaq社のサイトから ダウンロードすることができる.
VCのみの環境では,他の言語と同じく,E-PROPATHが提供するDLLを利用することになる. なお,E-PROPATHが提供するDLLは単独で使用できるようにコンパイルされているので, 上で述べたランタイムライブラリは必要はない.
以下,三つの場合について,VCからの利用法をまとめておく.
Developer Studioが共用できる場合
VCとVFが両方インストールされている場合
PROPATH DLLをVCから利用する方法
この場合はVCのプロジェクトにFortranのソースコードを直接追加することができる.
例えば,アンモニアPROPATHのKPAMESとPSTをCで書かれたメインプログラムから
呼び出す場合,JNH3.FORをプロジェクトに追加し,メインプログラムは
以下のように書く.
#include <stdio.h>
extern "C" void _stdcall KPAMES( int* kpa, int* mes );
extern "C" float _stdcall PST( float* t );
void main()
{
float t, ps;
int kpa = 1, mes = 1;
KPAMES( &kpa, &mes );
t = 1e2;
ps = PST( &t );
printf( "ps = %10.5f\n", ps );
}
通常通りメイクすれば実行ファイルができあがる.
この場合は,まずVFでOBJファイルかLIBファイルを作っておき,これを VCのプロジェクトに追加すればよい. Cのコードの書き方はDeveloper Studioが共用できる場合と同じである.
コマンドラインでやる場合は以下のようになる.
#include <stdio.h>
void _stdcall KPAMES( int* kpa, int* mes );
float _stdcall PST( float* t );
float _stdcall HPT( float* p, float* t );
void main(){
float t, ps, p, h;
int kpa = 1, mes = 1;
KPAMES( &kpa, &mes );
t = 2e2;
p = 1e0;
ps = PST( &t );
h = HPT( &p, &t );
printf( "ps = %10.5f\n", ps );
printf( "h = %10.5f\n", h * 1e-3 );
}
PROPATH 側の関数の引数はすべてポインタとして宣言する.
cl /c main.c
fl32 /c jh2o.for
link main.obj jh2o.obj
とすれば,main.exe が出来上がる.これを実行すれば,
ps = 15.54880
h = 2875.35725
と表示される. なお,スタティックライブラリ(.lib)をリンクする場合も,
link main.obj jh2o.lib
とすればよい. 関数宣言の注意点を以下にまとめておく.
動的リンク
E-PROPATHにはVCからDLLを呼び出すためのインポートライブラリは含まれないので, VCでDLLを呼び出す場合は,必然的に動的呼出しになる.
以下にプログラム例を示す.この例では,水のDLLをロードして,KPAMES,PSTおよび
HPT 関数へのアドレスを取得し,100degにおける飽和蒸気圧と200deg,10barにおける
比エンタルピーおよび比エントロピーを計算している.
#include <windows.h>
#include <stdio.h>
typedef void ( CALLBACK* PROPATH_KPAMES )( int, int ); // KPAMESを呼び出すための関数ポインタ型
typedef float ( CALLBACK* PROPATH_FUNC1 )( float ); // PSTを呼び出すための関数ポインタ型
typedef float ( CALLBACK* PROPATH_FUNC2 )( float, float ); // HPTおよびSPTを呼び出すための関数ポインタ型
void main(){
HINSTANCE hDLL;
PROPATH_KPAMES kpames;
PROPATH_FUNC1 func1;
PROPATH_FUNC2 func2;
float t, p, ps, h, s;
int kpa = 1, mes = 1;
hDLL = LoadLibrary( "jh2o.dll" ); // DLLをロード
if ( hDLL != NULL ){
kpames = ( PROPATH_KPAMES )GetProcAddress( hDLL, "KPAMES" ); // KPAMESのアドレスを取得
kpames( kpa, mes );
t = 1e2;
func1 = ( PROPATH_FUNC1 )GetProcAddress( hDLL, "PST" ); // PSTのアドレスを取得
ps = func1( t );
printf( "ps = %10.5f [bar]\n", ps );
t = 2e2; p = 1e1;
func2 = ( PROPATH_FUNC2 )GetProcAddress( hDLL, "HPT" ); // HPTのアドレスを取得
h = func2( p, t );
func2 = ( PROPATH_FUNC2 )GetProcAddress( hDLL, "SPT" ); // SPTのアドレスを取得
s = func2( p, t );
printf( "h = %10.5f [kJ/kg]\n", h * 1e-3 );
printf( "s = %10.5f [kJ/kgK]\n", s * 1e-3 );
FreeLibrary( hDLL ); // DLLを解放
}
}
ps = 1.01325 [bar]
h = 2826.78775 [kJ/kg]
s = 6.69216 [kJ/kgK]
となる.
Windows API を使うので,windows.hをインクルードし, GetProcAddress の戻り値を格納する適当な関数ポインタ型を最初に定義する. E-PROPATHが提供するDLLの関数の整数引数および実数引数はすべて値渡しで, 文字引数はヌル終端文字配列へのポインタである.
もう一つ例を示しておく.
以下のコードは水およびアンモニアのDLLをロードして,100degにおける
飽和蒸気圧を両方の物質に対して計算するものである.
#include <windows.h>
#include <stdio.h>
typedef void ( CALLBACK* PROPATH_KPAMES )( int, int );
typedef float ( CALLBACK* PROPATH_FUNC1 )( float );
typedef float ( CALLBACK* PROPATH_FUNC2 )( float, float );
void main(){
HINSTANCE hDLL_h2o, hDLL_nh3;
PROPATH_KPAMES kpames_h2o, kpames_nh3;
PROPATH_FUNC1 pst_h2o, pst_nh3;
float t = 1e2, ps_h2o, ps_nh3;
int kpa = 1, mes = 1;
hDLL_h2o = LoadLibrary( "jh2o.dll" );
hDLL_nh3 = LoadLibrary( "jnh3.dll" );
if ( ( hDLL_h2o != NULL ) && ( hDLL_nh3 != NULL ) ){
kpames_h2o = ( PROPATH_KPAMES )GetProcAddress( hDLL_h2o, "KPAMES" );
kpames_nh3 = ( PROPATH_KPAMES )GetProcAddress( hDLL_nh3, "KPAMES" );
kpames_h2o( kpa, mes );
kpames_nh3( kpa, mes );
pst_h2o = ( PROPATH_FUNC1 )GetProcAddress( hDLL_h2o, "PST" );
pst_nh3 = ( PROPATH_FUNC1 )GetProcAddress( hDLL_nh3, "PST" );
ps_h2o = pst_h2o( t );
ps_nh3 = pst_nh3( t );
printf( "water ps = %10.5f [bar]\n", ps_h2o );
printf( "ammnonia ps = %10.5f [bar]\n", ps_nh3 );
FreeLibrary( hDLL_h2o );
FreeLibrary( hDLL_nh3 );
}
}
water ps = 1.01325 [bar]
ammnonia ps = 62.35048 [bar]
となる. この例のように,一度に二つ以上のDLLをロードすることも可能である.
静的リンク
VCのコードと静的リンクが可能なDLLの作成方法を示す.
まず,DEFファイルに以下のような記述を追加する.
_PST@4 = JH2O_PST
_HPT@8 = JH2O_HPT
次に,以下の内容のヘッダファイルを作成する.
#define DLLIMPORT __declspec( dllimport )
#ifdef __cplusplus
extern "C" {
#endif
DLLIMPORT void __stdcall KPAMES( int, int );
DLLIMPORT float __stdcall HPT( float, float );
DLLIMPORT float __stdcall PST( float );
#ifdef __cplusplus
}
#endif
#include <stdio.h>
#include "ppropath.h"
void main (int argc, char *argv[])
{
int kpa = 1, mes = 1;
float t, ts, p, h, hd, hdd, tc, pc;
KPAMES( kpa, mes );
t = 1e2;
ps = PST( t );
printf( "ps = %10.5f\n", ps );
}
このコードをmain.cppなどの名前で保存する. jh2o.dllのインポートモジュールであるjh2o.libとリンクするには,
cl main.c jh2o.lib
とする. Developer Studioを使う場合は,プロジェクトにjh2o.libを追加する. ただし,この場合はバージョンの整合性が必要になるようである. すなわち,例えば,VC5のDeveloper Studio上で用いることのはVF5で作成したLIBだけであり, VF6で作成したものはリンク時にエラーが発生する. Compaq社もバージョンが整合したVCとVFを使うことを推奨している.
SEO | [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送 | ||