17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NimAdvent Calendar 2018

Day 16

NimとC言語の連携

Last updated at Posted at 2018-12-15

https://qiita.com/snowlt23/items/1696687cca61bfedb1cc で取り上げられていた内容の拡張といった感じ。

ご存知の通り、Nimはいろんな言語との連携が可能です。
今回紹介するのは主にCとNimとで関数を共有する方法です。

注意 :
・コンパイル時「test.nim」の「.nim」は省略可能ですがあえて残しています。

C言語の関数をNimで利用

ファイルから宣言

Cのコードのほうの拡張子は「.h」でもOKです。

一つずつ宣言する

test.c

int dfunc(int b){
    return b-1; // 引数に1を引いた数を返す
}

int cfunc(int a){
    return a*2; // 引数に2を掛けた数を返す
}

このdfunccfuncをNimで使ってみましょう。

test.nim
# 宣言
proc function(a:cint):cint{.header:"[CFILE」",importc:"dfunc".}
# 「CFILE」にtest.cのパスを入れる<<絶対パス、またはnimcacheからの相対パス>>
#  例 : {.header:"C:/Code/test.c",importc:"関数名".}

proc cfunc(a:cint):cint{.header:"「CFILE」".}
#  同じ関数名の場合はimportcが省略できる(ここでは{.importc:"cfunc".}が適用される)


echo function(12)
echo cfunc(12)

# ここでは 12

で、test.nimをビルドします。

console
> nim c -r test.nim
11
24

ファイルごとにまとめて宣言

push - pop を使うことによりheaderプラグマを省略しています。

test.nim
# 宣言

{.push header:"../test.c".}  # header : ... を省略する

proc function(a:cint):cint{.importc:"dfunc".}
proc cfunc(a:cint):cint
# 関数の中身はさっきと同じ

{.pop.}

echo function(12)
echo cfunc(12)
# 出力もさっきと同じ

ライブラリから宣言

ここでは、Cのファイルは使用しません。
ライブラリから直接関数を持っていきます。

test.nim
{.push header:"<stdio.h>".} # 標準ライブラリ"stdio.h"

proc printf(a:cstring,b:auto) # {.header:"<stdio.h>".}
proc scanf(x:cstring,y:auto)

{.pop.}

var n:char

scanf("%c",n.addr)
printf("Hi, I am C Library!\ncharacter:%c",n)

これで、C言語で使った時とと同じ挙動が再現されます。

console
> nim c -r test.nim
> t
Hi, I am C Library!
character:t

Nimの関数をCで利用

ちょっと手間がいります。

test.nim
proc nitest(a:int):int {.exportc.}=
    return a+8 # 引数に8を足した数を返す

# exportc プラグマを忘れずに!

これを、次のようにビルドします。

console
> nim c --noMain --noLinking --header:test.h test.nim

( test.hのところをtest.c と書いても同じ結果です )

すると、nimcacheにtest.hという名前のファイルが生成されたはずです。
これをCに使わせます。

test.c
#include "test.h"
#include <stdio.h>

int main(){
    NimMain();
    printf("%d\n",nitest(7)); //ここでは例として 7
}

これを、

console
 > gcc -o test.exe -Inimcache -I"「LibPATH」" nimcache/*.c test.c

LibPATHには、Nimのコンパイラのlibファイルのパスを入れてください。
これでコンパイルできるはずです。

console
> ./test.exe
15

最後に

もう気づけば真冬ですね。
冬はこたつでNimやろうぜ

17
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?