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

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

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

3回答

4180閲覧

RustでWindowsのDLLを作成したい

suigin

総合スコア9

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

1グッド

1クリップ

投稿2020/05/05 08:57

前提・実現したいこと

Rustを使用してWindowsのDLLを作成し、それをExcelのVBAから呼ぶことを考えています。

発生している問題・エラーメッセージ

DLLをビルドできましたがVBAから呼ぶ際に「ファイルがみつかりません」というエラーが出ます。DLLのパス自体は間違っていないで、どうもDLL内の関数が見つからないためこのエラーが出ているようです。
Visual StudioでC#のプロジェクトを作って同じDLLを呼び出すと「XXX.dll' を読み込めません:指定されたモジュールが見つかりません。 (HRESULT からの例外:0x8007007E)'」となっているのでEXCELの問題ではないと思います。

RustでWindowsのDLLを作成するには何が足りないのかを教えてください。

該当のソースコード

DLL部分は hello.rs という名前で次のように記述しています。

Rust

1#[no_mangle] 2pub extern "system" fn hello(count: i32) -> i32 { 3 if count < 0 { 4 return 0; 5 } 6 return 1; 7} 8 9#[no_mangle] 10pub extern "system" fn hello2() { 11}

Cargo.toml は次のように設定しています。

Cargo.toml

1[package] 2name = "main" 3version = "0.1.0" 4authors = [""] 5 6[lib] 7name = "hello" 8path = "src/hello.rs" 9crate-type = ["dylib"] 10

EXCELのVBAは次のコードです

vba

1#If Win64 Then 2 ' 64Bit ?? 3 #Else 4 ' 32Bit ?? 5 Private Declare Function hello2 Lib "(ここはフルパスです)\hello.dll" (ByVal a As Long) As Long 6#End If 7 8Sub test() 9 C = hello(1) 10 hello2 11End Sub 12

試したこと

ビルドしたDLLをDependency Walkerで調べてみると、次のエラーが出ました。


Error: At least one required implicit or forwarded dependency was not found.
Warning: At least one delay-load dependency module was not found.


hello,hello2の関数がDLLの中にあることは出力されています。

補足情報(FW/ツールのバージョンなど)

開発環境はVSCでWindows10 64bitで開発しています。
EXCELは2010の32bit版

kawayan_c👍を押しています

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

追記

引数があるRustの関数を呼び出す場合はABIを正しく設定しないと呼び出せませんでした。

32bitのアプリケーションから呼び出す場合は"stdcall"
64bitのアプリケーションから呼び出す場合は"win64"

32bitのExcelのVBAから呼び出したい場合は、以下のように記述しないとDLL呼び出しのエラーになります。

Rust

1pub extern "stdcall" fn hello(count: i32) -> i32 {}

引数がない関数を呼び出す場合はABIがあってもなくても問題ないようです。

投稿2020/05/08 13:32

suigin

総合スコア9

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Rustが64bitのDLLを生成していたので、Windowsでも64bitのDLLとして読み込むようにしないと、DLLが見つからないというエラーになることが原因のようです。

自作でWindowsのコンソールアプリを作成して試したところ、ビルドのCPUの設定を"x64"にすると読み込め、"x86","anyCPU"では読み込めないため、64bitで処理をしなければならないようです。自分が使用していた32bitのEXCELでは読み込むことができないようです。

ABIの設定(pub extern "C" fn Hello2() { の記述)を"cdecl"や"stdcall"にすると32bitのDLLが生成されるような記述がしてありましたが、どうも64bitのDLLしかビルドされないようです。
https://doc.rust-lang.org/reference/items/external-blocks.html#abi

とりあえずはこれが原因と考えて、別の手段を探します。

投稿2020/05/06 03:03

suigin

総合スコア9

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tatsuya6502

2020/05/06 03:20

なるほど。32ビットと64ビットの違いでしたか! それでしたら、targetとして32ビットMSVC ABIを指定すればいいのかもしれません。 rustup target add i686-pc-windows-msvc cargo build --release --target=i686-pc-windows-msvc DLLは /target/i686-pc-windows-msvc/release/ に出力されます。
suigin

2020/05/06 03:59

この方法を使ってビルドしたところ、32bitのExcelから呼び出すことができました。 ありがとうございます。
tatsuya6502

2020/05/06 08:41

とりあえずは解決したようでよかったです。
guest

0

ベストアンサー

crate-typedylibからcdylibへ変更してみてください。多分、これでうまくいくと思います。

toml

1crate-type = ["cdylib"]

dylibを指定したときに生成されるdllはRustで書かれたプログラムから使用されることが想定されており、余分な情報が入っているようです。ExcelのようなRust以外の言語で書かれたプログラムから使用するときはcdylibを指定します。

参考: Linkage - The Rust Reference

追記(2020/5/6 09:30 +0900)

いま手元にWindows環境がないので試せないのですが、2年ほど前に試したときはcdylibを指定することに加えて、以下の点も注意する必要があったように思います。(うろ覚えですし、いまは変わっているかもしれません)

  • .dllファイルの他にもうひとつファイルがないと動かなかった(?)
  • .dllかもうひとつのファイルかどちらかの中に、相手のファイルのフルパスが埋め込まれていた。そのため、それらのファイルを元の場所から移動すると動かなくなってしまった(?)

その時はRustで作ったDLLをCプログラムから呼び出す実験をしてました。もうひとつのファイルの拡張子がなんだったのか思い出せないのですが、Cargoでビルドしたときに./target/release直下にDLLと一緒に出力されるはずです。

cdylibを指定しても解決しない場合は、それに加えて以下も試してみてください。

  • (もしまだ試してなかったら).dllファイルを./target/releaseから移動せずにVBAから読み込んでみる。

追記(2020/5/6 09:45 +0900)

もうひとつのファイルの拡張子がなんだったのか思い出せないのですが、

確認したところ.libでした。このファイルはimport libraryといって、DLLを利用するプログラム側の コンパイル時 に必要なようです。実行時はそのファイルのことは無視していいのかもしれません。

投稿2020/05/05 13:27

編集2020/05/06 00:45
tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suigin

2020/05/06 02:50

回答ありがとうございます。 ただ、上記の方法でもうまくいかず、どうも「Rustが64bitのDLLを生成しているので、Windowsも64bitで処理をしなければならなかった」が原因のようです。 Windowsのコンソールアプリのビルドの設定でCPUを"x64"にするとDLLが読み込め、"x86","anyCPU"では読み込めないことがわかりました。自分の環境のEXCELが32bitなので64bitのDLLをうまく読み込めていないようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問