2016-09-27 26 views
5

とCインタフェースIは、Cライブラリを使用していますジュリアパッケージを拡張しています。私はジュリアからいくつかのC関数を呼び出す必要があります。彼らはこのような何かを見て:私もジュリアの対応するタイプと宣言しているジュリア - 高調種類

struct contained { 
    int x; 
    int y; 
    int z; 
}; 
struct mystruct { 
    int n; 
    contained* arr; 
}; 
mystruct* mk_mystruct(int n, contained* arr); 
void use_mystruct(mystruct* foo); 

:引数としてcontained*を取る

type contained 
    x::Int64 
    y::Int64 
    z::Int64 
end 
type mystruct 
    n::Int64 
    arr::Array{contained, 1} 
end 

ccallに機能を、すべてがPtr{Int64}としてcontained*の治療正常に動作します:

con = fill(0, 5, 3); 
mys = ccall((:mk_mystruct, "mylib"), Ptr{mystruct}, (Int64, Ptr{Int64}), n, con) 

containedは同じm em64の配列としてのemoryレイアウト。これは、Juliaパッケージ内の他の場所でも同様に行われます。しかし、返されたmystructの値を調べるために私が知っている唯一の方法は、unsafe_loadで逆参照することです。その時点で、Juliaはsegfaultからクラッシュします。 Juliaのポインタを逆参照する正しい方法は何ですか?

Cライブラリも含まれて機能し、その代わりに、私は不透明としてポインタを扱い、このC関数に戻って、それを渡すことができジュリアにポインタデリファレンスのかなり印刷:Cコードで

void print_mystruct(mystruct* foo, FILE* outputfile) 

を、これはoutputfile=stdoutで呼び出されます。 ccallでこれをどのように設定しますか?これは明らかに動作しません:

ccall((:print_mystruct, "mylib"), Void, (Ptr{mystruct}, Ptr{Void}), mys, stdout) 

私はPtr{Void}stdoutの代わりに置く必要がありますか? JuliaはCインタフェースでI/Oをどのように実装していますか?

+0

なぜ 'Int64'をCの' int'に対応する型として使うのですか? 'int'は普通32ビットで、おそらくは16ビットのように狭く、他にも多くのサイズがあります。 – chux

+0

実際に私は 'Int'を使用しましたが、' Int'は私のマシン上で 'Int64'を意味するので、混乱しないように' Int64'を上のコードに入れました。私の理解では、Juliaが適切なサイズのIntを検出するので、このマシンCのintも64ビットです。あれは正しいですか? –

+1

C言語の 'int'のサイズは、プロセッサではなくコンパイラとオプションによって制御されます。さまざまな理由で、32ビットと64ビットの両方の 'int'が64ビットマシン用のコンパイラで検出されます。 – chux

答えて

3

あなたはジュリアで型を宣言すると、あなたはCと同じ種類の宣言する必要があります:ジュリアタイプArray{contained, 1}はCでjl_value_t*に対応するであろうと、ジュリアタイプIntはC.にintptr_tに対応するであろう

type contained 
    x::Cint 
    y::Cint 
    z::Cint 
end 
type mystruct 
    n::Cint 
    arr::Ptr{contained} 
end 

プラットフォームに依存しない方法で、stdoutへのハンドルを取得する方法がわかりません。ほとんどのプラットフォームでは、実際のシンボル名を見つけるためにCヘッダーマクロを展開する必要があります。例えば、MacOSの上で、それが__stdoutpにリネームされます:

julia> unsafe_load(cglobal(:__stdoutp, Ptr{Void})) 
Ptr{Void} @0x00007fff751f7348 

julia> ccall(:fprintf, Csize_t, (Ptr{Void}, Cstring, Cint...), ans, "hi\n") 
hi 
0x0000000000000003 

あなたは自動的にヘッダファイルを解析から、これらの定義を生成することができClang.jl packageをチェックアウトするに興味があるかもしれません。

+0

私は 'Int64'をどこでも' Cint'に置き換え、 'Array {contained、1}'を 'Ptr {contained}'に変更しました。今度は 'mk_mystruct'が正しいことを確認したいので、' Base.show(m :: mystruct) 'を定義します。 'Array {contained、1}'ではなく、 'Ptr {contained}'でこれをどうすればいいですか? Juliaのポインタと配列の間に関係はありますか? –