質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.62%

Nimで文字列を扱うdynlib(.dll)を作成しPythonから使用したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 968

namnium1125

score 2021

いつもお世話になっております。m(_ _)m

どうしてもPythonからNimで作成したツールを使用する必要があり、また少し大きめの文字列をNimで作成したツールからPythonに渡さなければならず、色々調べたのですが自分ではわからなかったので質問させてください。

後述しているように他の方法を検討してみたのですがうまくいかず、現在はdllでやり取りできないかと考えております。
そこで以下のようにしてみました。(モデルです。)

fuga.nim

proc hoge(): cstring {.exportc, dynlib.} =
  result = "hoge"

dllファイル化

$ nim c --app:lib fuga.nim

fuga.py

from ctypes import cdll
import ctypes

dll = cdll.LoadLibrary('./fuga.dll')
hoge = dll.hoge
print(hoge()) # => 自分の環境では1802407936になりました。

しかし、コメントアウトに示すように、整数値が表示されてしまいました。

おそらく文字配列のアドレスか何かかと思い、Nim側でptraddr関数を使用し、Python側でc_bufferを使用する、といったことを行ったのですがこれもうまくいきませんでした。

proc hoge(st: var ptr cstring) {.exportc, dynlib.} =
  var hoge = cast[cstring]("hoge")
  st = hoge.addr
from ctypes import cdll, c_buffer
import ctypes

st = c_buffer(b"", 32)
dll = cdll.LoadLibrary('./fuga.dll')
hoge = dll.hoge
hoge(st)
print(st.value) # => b'X\xee\x1e\xb7Y' # 実行毎に変動しました

どうすればdllを介して文字列をやり取りできるのでしょうか?

ファイル等を介してやり取りするのではなく、dllを使用しなければならない理由は、実際のコードでは関数呼び出しを相当な回数行う必要があり、処理時間が膨大になってしまうと考えているからです。

始めはpexpectを使用して子プロセスとしてやり取りすることを考えていたのですが、Windowsだとwinpexpectを使用しなければならずさらに試してみてダメだったので断念しました。(subprocessが使えないのはインタラクティブなやりとりが必要だからです。)

ダイナミックリンクライブラリ自体、必要に迫られて先ほど触り始めたのでほとんど理解していません。。

この分野に詳しい方、もしくは何か解決策の糸口となる方法をご存知の方がおりましたら、何卒よろしくお願いいたします。m(_ _)m

 環境

  • Python 3.6.4 :: Anaconda, Inc.
  • Nim Compiler Version 0.18.0 [Windows: amd64]
  • MINGW64_NT-10.0 **** 2.10.0(0.325/5/3) 2018-02-09 15:25 x86_64 Msys
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

nimって知らないのですが、おそらく

/*
proc hoge(): cstring {.exportc, dynlib.} =
  result = "hoge"
*/
const char * hoge()
{
  return "hoge";
}

というCの関数と同様だと思うので、そのつもりで回答します。

とりあえず、マニュアル。

上記によれば、関数の属性「restype」にctypesの型を指定すれば、その型にあったオブジェクトに変換してくれるそうです。

from ctypes import cdll, c_char_p

dll = cdll.LoadLibrary('./fuga.dll')
hoge = dll.hoge
hoge.restype = c_char_p
print(hoge())

でどうですか。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/15 21:56

    その方法でうまくいきました!ありがとうございます!

    返り値の型をPython側で指定する必要があったのですね..ctypesについて理解が足りておりませんでした(^ ^;

    ベストアンサーとさせていただきます。改めてありがとうございました。m(_ _)m

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る