トップ回答者
VS2010+VB.net DEF ファイルを使った DLL からのエクスポート

質問
-
VB.netを使ってDLLを作成していますが、関数のエクスポート方法がわかりません。
新しいプロジェクト → クラスライブラリー から新規のDLL(ファイル名:NewDLL.dll)を作成し、初期状態で作成されるClass1.vbを次のように書き換えました。
ここで、関数c1をエクスポートしたいと考えています。
Public Class Class1
Public Shared Function c1(ByVal s As String) As Int32
Return s.Length
End Function
End Class
ソリューションエクスプローラーのルートには、「NewDLL.def」を追加しています。
NewDLL.def(テキストファイル)の内容
LIBRARY NewDLL
EXPORTS
c1 @1
以上のようにしてコンパイルすると、正常にコンパイルはできるのですが、生成された「NewDLL.def」を外部から参照してもc1が見えません。
(dumpbin.exe /exports NewDLL.dll として動作しないのを確認済みです。)
どうすればエクスポートができるのか、御教授を御願い致します。
回答
-
できません。VB.NETなど.NET Frameworkを使用する言語は「マネージド」な世界となります。一方、エクスポートできる関数は「ネイティブ」な世界となります。両者を混在させるには種々の条件があり、少なくともエクスポートは不可能です。
# 例に挙げられている関数ですと、引数にStringを受け取っていますが、このStringオブジェクトは.NET GCによって管理されている必要があり、ネイティブでは扱えません。これは一例であり、この問題を解決したからといって改善されるものではありません。
なぜ、エクスポートしたいという考えに至ったのか、その理由を挙げて頂けたら別のアプローチが提案できるかもしれません。
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月19日 7:35
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月22日 1:09
-
VBコンパイラーをコマンドプロンプトで動作させ、ソースファイルとdefファイルを明示してコンパイルさせれば良いのではないかと考えています。現在トライ中です。
↑ これでも実現不可能ですか?
できません。
C# や VB.NET のコンパイラーは関数エクスポートの機能を持っていませんので、どのような方法であっても、これらのコンパイラーを最終的に使う方法では実現できません。そういう状況で荒技として第三者から提供されているのが、Unmanaged Exports や DllExport なのでしょう。
普通はやらないことなので、それなりの応用力を求める点は頑張ってもらうしかありません。Microsoft が提供する範囲の正攻法はすでに指摘のあるとおり、C++/CLI 経由で公開する方法のみです。
エラーが出るとか、英語だからと逃げずに立ち向かうか、C++/CLI というさらに茨の道に進むか、諦めるかの3択かと思います。
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月24日 0:51
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月22日 1:09
すべての返信
-
できません。VB.NETなど.NET Frameworkを使用する言語は「マネージド」な世界となります。一方、エクスポートできる関数は「ネイティブ」な世界となります。両者を混在させるには種々の条件があり、少なくともエクスポートは不可能です。
# 例に挙げられている関数ですと、引数にStringを受け取っていますが、このStringオブジェクトは.NET GCによって管理されている必要があり、ネイティブでは扱えません。これは一例であり、この問題を解決したからといって改善されるものではありません。
なぜ、エクスポートしたいという考えに至ったのか、その理由を挙げて頂けたら別のアプローチが提案できるかもしれません。
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月19日 7:35
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月22日 1:09
-
御回答ありがとうございます。
>なぜ、エクスポートしたいという考えに至ったのか
開発依頼者から提示された仕様ですので、変えずにいきます。
こちらはVB.netでDLLを作成し、依頼者はDLLを参照するプログラムをC#で作成します。
参照元、参照先とも.NET Framework開発環境で、この様なFunctionを公開することもできないのでしょうか。
Public Function c2(ByVal strb As System.Text.StringBuilder) As Int32messagebox.show(strb.tostring)
Return -1
End Function- 編集済み huahi11112 2017年7月19日 5:05
-
.net間の話なら、クラス・メソッドをPublicにしておく程度で良いのでは。
そのように造ったDLLを、使用者側で「参照に追加」してやれば、そういうメソッドは呼べるようになります。あくまでも、.Netのクラス・メソッドの公開、という概念によります。
ネイティブな「関数」を公開する(DLLのEXPORTテーブルに載せる)とは別概念になります。こちらを実現したいのであれば(.NET間なのに、何故Unmanaged Interopを挟むんだ、という疑問は残りますが)Unmanaged Exportsが使えるかもしれません。
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexportsjzkey
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年8月22日 1:09
-
開発依頼者から提示された仕様ですので、変えずにいきます。
依頼内容を誤解している可能性があります。本当にDEFファイルを使ったDLLからのエクスポートが指示内容なのでしょうか? エクスポートされれば手段は問わないのでは?
-
>エクスポートされれば手段は問わないのでは?
その通りです。VB.netでの解決手段をお聞きしているのです。勝手に誤解させないで下さい。
- 編集済み huahi11112 2017年7月19日 22:46
-
開発依頼者から提示された仕様ですので、変えずにいきます。
こちらはVB.netでDLLを作成し、依頼者はDLLを参照するプログラムをC#で作成します。
佐祐理さんの指摘を飲み込めていない可能性もあるかなと感じたので書いておきます。
VB.NET で Public としたクラスは、他の C# や VB.NET アプリケーションから参照設定することで、利用することができます。
その使い方は特に def ファイルとか必要ありません。
この状態を、Public = 公開されている = エクスポート(外部に公開)されているということなので、「エクスポートされていれば何でも良いのでは?」=「依頼者が関数形式のエクスポートという風に形式を定めていないのでは?」と問いただしています。仮に依頼者が「関数形式のエクスポート」を明示的に求めていたとしても、C# から VB.NET のコードを利用するために関数形式を経由するメリットはありませんので、確認し直した方がよいです。
-
Unmanaged Exportsは魅力的な解決方法だと思ったのですが、「対象CPUをAnyCPUとすると動作しない」という仕様でした。x86でコンパイルするとSyntax Errorが出ます。エラーの内容も意味不明な行番号等の羅列で、発生箇所が特定できません。リファレンスマニュアルが無いので、これ以上はどうしようもないと判断し、使うのをやめました。
- 編集済み huahi11112 2017年7月21日 7:09
-
どうしても、Exportテーブルを持つManagedなDLLが作りたいみたいなので、まあ、そこには深入りしません。
PEヘッダ(DLL)の仕様として、EXPORTテーブルのあるDLLはAnyCPUにはできません。そもそもネイティブにAnyCPUなDLLは存在しないので。
Unmanaged ExportsですがDllExport( https://github.com/3F/DllExport )が実質的な後継みたいですね。ソースもついてますし。
Microsoft的に正当なやり方(EXPORTテーブルを持つManaged DLLを作る方法)は、VBのDLLを参照するC++/CLIのDLLを用意してそいつにDEFファイルを食わす方法ですか。
jzkey
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年8月22日 1:09
-
VBコンパイラーをコマンドプロンプトで動作させ、ソースファイルとdefファイルを明示してコンパイルさせれば良いのではないかと考えています。現在トライ中です。
↑ これでも実現不可能ですか?
できません。
C# や VB.NET のコンパイラーは関数エクスポートの機能を持っていませんので、どのような方法であっても、これらのコンパイラーを最終的に使う方法では実現できません。そういう状況で荒技として第三者から提供されているのが、Unmanaged Exports や DllExport なのでしょう。
普通はやらないことなので、それなりの応用力を求める点は頑張ってもらうしかありません。Microsoft が提供する範囲の正攻法はすでに指摘のあるとおり、C++/CLI 経由で公開する方法のみです。
エラーが出るとか、英語だからと逃げずに立ち向かうか、C++/CLI というさらに茨の道に進むか、諦めるかの3択かと思います。
- 回答の候補に設定 立花楓Microsoft employee, Moderator 2017年7月24日 0:51
- 回答としてマーク 立花楓Microsoft employee, Moderator 2017年8月22日 1:09
-
個人的に興味があったので「VB.NET で書いた クラスライブラリを C++ で読み込む実験」試してみました。
利用したのはこの仕組み
通常は DLLをどう作ってもエクスポートテーブルができないのですが。
デコンパイルして、エクスポートテーブルを注入して再コンパイルするという仕組みになっています。
VB.NET 2017で試したところ、問題なくエクスポートできました。
ソースはこんな感じになりますが、ビルド後のイベントにダウンロードしたコンポーネントを自分で入れて、処理します。
Public Class Class1
<ExportDllAttribute("ExportDemoFunction">
Public Shared Function Func(ByVal num1 As Integer, ByVal num2 As Integer) As Integer
Return num1 + num2
End Function
End Class
- 編集済み 黒翼猫・ω・) 2022年1月28日 11:00
-
この案件、「絶対にできない」という回答が寄せられたことから依頼者と協議して別の方法で回避したのでその後気に掛けることは無かったのですが、関連する開発依頼が来たら試用してみたいと思います。
「通常はできません」は変わっていませんし、2017 年当時も話題になっていた外部ツールを使う手法が1つ増えただけ ですので…。
2017 年当時も「絶対にできません」ではなく、「DEF ファイルを使って VS ではできない。外部ツールでなら…」みたいな話だったと思います。(情報は寄せられていました)なお、今回紹介された記事は .NET Framework 2.0 向けに 2006 年に書かれた内容のようなので、実際にやりたいなら、当時から紹介されている DllExport (https://github.com/3F/DllExport ) を考えた方が良さそうに見えます。2021 年時点でもコミットが続いていることから。
-----
質問に対して「なぜ依頼者から与えられた仕様が***なのかという理由を説明しなければ回答を拒む」という姿勢の回答者さんが今までに多くいて困りました。
なぜ、回答者がそれをやりたいのかを問うのは、「正道から外れているのでリスクがある」からです。
各々の経験から「もっと楽な方法」「安定的な方法」を採用した方がリスクは少なくなるであろうという考えから、目的・理由・背景を問うわけです。
絶対的に覆せない要件なら、「この要件は〇〇から強く要求されていて、変更できないので、要件見直しの投稿はご遠慮ください」などと一言書き添えればよいです。それでも絡んできて、平行線になりそう(自分に響く内容がない)なら無視すればよいだけです。-----
個人的には、トリッキーなやり方は、後任の人、納品物を受領した人が理解できない、扱えないかもしれませんし、調べようとしても正道ではないので情報が足りない、わからないなど難題を抱えるので、できるだけ要件の見直しの可能性がないか、確認、交渉しますね、依頼を受けたならば。
C ベースの API 風の関数の場合、関数を呼び終えたらメモリを解放することをユーザーは期待するかもしれません。
しかし、.NET Framework の DLL が大量に読み込まれたものは解放されないし、.NET Framework のオブジェクトは GC で管理されているので即座にメモリ解放するわけではない。これを不具合だ・瑕疵だと言われたら対処方法がないので泣けます。他にも構造体で受け渡ししたいとか、オブジェクトの状態を保持したいとなったときに、これらのツールはどのように解釈するのだろうと調べないといけません。
C++/CLI なら自分で制御できますので、その辺も安心感はあります。趣味・私事の範囲ではそうそう問題にならないと思いますが、ビジネスで使うなら慎重になった方がいいだろうという印象です。(特に日本市場は完璧を求められがちであるため)
- 編集済み AzuleanMVP, Moderator 2022年1月29日 0:59
-
質問に対して「なぜ依頼者から与えられた仕様が***なのかという理由を説明しなければ回答を拒む」という姿勢の回答者さんが今までに多くいて困りました。
Azuleanさんの回答に同意であり、もう少し補足すると、私個人としてはQ&Aサイトの目的であるQ&Aの蓄積、その観点で有益ではないと判断したからです。
つまり、Q&Aサイトでなく、教師として雇われたり、もしくは業務として指示を受けた場合には拒まないです。必要ならDllExportも提案しますし、きっとC++/CLIを使うことになるとは思います。
繰り返しになりますが、Q&Aサイトとは質問者さんの課題に応える場ではなく、質問者さんと同様の問題を抱えている人に有益な回答を示す場だと考えています。質問者さんを除く他の閲覧者さんに有益であると判断した場合は質問者さんの意に反した回答を投稿します。
-
こんにちは、なんか、私が掘り返したネタで議論になってるみたいですみません。
> 2017 年当時も「絶対にできません」ではなく、「DEF ファイルを使って VS ではできない。外部ツールでなら…」みたいな話だったと思います。(情報は寄せられていました)
2017年当時も 、寄せられていた情報が VC#での話だったので、VB.netでの解決手段を望まれていたのだと思います。
(DEFを使ってできるかどうかは重要ではない印象を受けました)
私が試したのも、「VB.netで dllexport を使う」というのをやってる人がいないようだったので
VC#ではなくVB.netでも実現できるか確認するためだったのでした。
(内部に詳しい人からしたら、VC#も VB.netもインターフェイス違うだけで中身ほぼ同じものなので、
できるだろうと想像できるかもしれませんが、そういうUIが VB.net向けに解放されているかが問題だったのかなと…)
-
2017年当時も 、寄せられていた情報が VC#での話だったので、VB.netでの解決手段を望まれていたのだと思います。
(DEFを使ってできるかどうかは重要ではない印象を受けました)
私が試したのも、「VB.netで dllexport を使う」というのをやってる人がいないようだったので
VC#ではなくVB.netでも実現できるか確認するためだったのでした。
2017/7/21 の投稿(「これ以上はどうしようもないと判断し、使うのをやめました。」を含む文章)によると、チャレンジされてエラー解決が困難と諦められていたように思います。
言語の壁が原因だったかは不詳です。
その後、続く投稿で「いくらメリットが無くても構いませんから、defファイルを使った解決方法を教えて下さい。」と手法を限定されたので「(def ファイルでは)方法がない」で結論付いたという認識です。
C# であろうと、VB.NET であろうと、UI 面のフォローはないので、ツールを使った工夫と頑張りが必要なのは変わらず、技術的な情報という観点ではこのスレッドの役目を終えているでしょう。
それ自体には別に異論はないのですが、コメントを続いてしまっているのは、回答側には回答側なりの考えがあるという反論だけです。
もっとも、すれ違いのままになるなら、これ以上伸ばす価値はないかもしれませんので、数年ぶりに投稿が続いている現状を気にする必要はなく、そのまま寝かせてしまって良いかと思います。
(このスレッドの発端は「依頼者が C# で使う DLL 開発」だったので、依頼者側の要件緩和や理解不足の解消か、受託側の提案・交渉での解決が理想だろうとは思っていますが、第三者だからこそ言えることかもしれません)- 編集済み AzuleanMVP, Moderator 2022年1月29日 8:36