ここから本文です

C#からアンマネージドDLLを作成する事は可能ですか?直接は無理でも逃げ道のような...

pli********さん

2015/10/1616:33:46

C#からアンマネージドDLLを作成する事は可能ですか?直接は無理でも逃げ道のようなものはありますか?

この質問は、活躍中のチエリアン・専門家に回答をリクエストしました。

閲覧数:
931
回答数:
3
お礼:
100枚

違反報告

ベストアンサーに選ばれた回答

abi********さん

2015/10/1707:46:56

かなり間接的になります。
説明の便宜上、まず直接的な手法を説明します。
ただし、その直接的な手法では、かなり問題があります。
その問題点を解決するために、どんどんと間接的な手法になって行きます。



====================================
[Win32 EXE で、.NET系機能を活用する方法 <ステップ1>]
====================================

まず、Win32 でのWindows アプリケーション(すなわち、Win32 系のEXE)のプロジェクトを作成します。
次に、[プロジェクト] - [プロパティ]で、「プロパティ ページ」画面を表示します。
表示された「プロパティ ページ」画面で、ツリー状の選択項目がありますので、そこで [構成プロパティ] - [全般]を選択します。
上記項目選択をすると、同じく「プロパティ ページ」画面で「共通言語ランタイム サポート」と言う入力項目が出てきますので、それを[共通言語ランタイム サポート(/clr)]を選択します。
次に、[ OK ]ボタンをクリックします。

上記の設定を行なえば、C++/CLI文法の記述で、.NET系機能(C# や VB.NET で使っている基本機能)を使えます。
なお、「共通言語ランタイム サポート(CLR)」については、下記を参照して下さい。
https://msdn.microsoft.com/ja-jp/library/k8d11d4s.aspx
https://msdn.microsoft.com/ja-jp/library/8bs2ecf4.aspx

しかし、上記手法では、大きな問題点があります。



====================================
[ネイティブとマネージを混合した場合の問題点]
====================================

上記方法の類の手法では、大きな問題点があります。
マネージコードとネイティブコード(アンマネージコード)が混合しているので、ネイティブコードが使用しているメモリ領域をガベージコレクション(マネージ系のメモリ管理用プログラム)が勝手に使ってしまいます。
すなわち、ネイティブ系(アンマネージ)のメモリ領域が、重複して誤動作します。


[Win32 EXE で、.NET系機能を活用する方法 <ステップ2>]
上記の「Win32 EXE で、.NET系機能を活用する方法 <ステップ1>」の類の情報は、「共通言語ランタイムサポート」のキーワードでインターネット検索すれば、情報が出てきます。
そこで、インターネット上の情報では、混合の問題点を解決するために、下記の方法を行なうように指示しているものもあります。
それは、通常よくあるWin32 EXE からWin32 DLL を呼び出すと言う構成です。
すなわち、<ステップ1>では、Win32 EXE を[共通言語ランタイム サポート(/clr)]設定にしましたが、ここでは(<ステップ2>では)、Win32 DLL を[共通言語ランタイム サポート(/clr)]設定にします。
これは、「DLL が混合状態ならば、EXE 側まで直接被害が及ばないでしょう」と言う考え方です。
ただし、EXE 側プログラムにDLL をリンクすると、DLL 用メモリ領域は、EXE 用メモリ領域内に配置されます。
すなわち、結局同じことで、混合問題の被害が、EXE 側に直接及びます。

構成図1
<Win32 EXE> --- <マネージ風Win32 DLL>



====================================
[Win32 EXE で、.NET系機能を活用する方法 <ステップ3>]
====================================

ところで、16ビット時代では、あるプロセスから、他のプロセスのメモリ領域をアクセスすることが可能でした。
しかし、これは、セキュリティ上問題ですので、32ビット時代とそれ以降では、プロセス間のメモリアクセスは、無理な仕組みになりました。
ただし、16ビット時代のシステムを32ビット用に作り直す場合、全体的構成の根本が変わってしまうので、移植が大変です。
よって、DLL を経由してならば、プロセス間のメモリ共有を許すようになっていいます。
図にすると、下記の通りです。

構成図2-1
<Win32 EXE> --- <Win32 DLL(共有DLL)> --- <Win32 EXE>

上記と、前述の<ステップ2>の手法を組み合わせれば、混合の問題を解決することが可能です。
すなわち、

構成図2-2
<Win32 EXE> --- <マネージ風Win32 DLL(共有DLL)> --- <C++/CLI で作るマネージEXE>

とします。
ここで、「なんで、

<Win32 EXE> --- <マネージ風Win32 DLL(共有DLL)> --- <C# で作るマネージEXE>

としないのか」と言う疑問が生じると思います。
しかし、上記構成では、混合の問題を解決していません。
混合の問題を解決するために、

<Win32 EXE> --- <マネージ風Win32 DLL(共有DLL)> --- <C++/CLI で作るマネージEXE>

とします。
ここで、<マネージ風Win32 DLL(共有DLL)>には、マネージコードの記述を、必要最小限のコードのみとします。
そして、<C++/CLI で作るマネージEXE>のほうで、マネージコードの記述をします。
なお、C++/CLI と言うプログラミング言語では、マネージコードとネイティブコード(アンマネージコード)の混合が許されています。
許されていると言っても、そのまま普通に混合してよいと言う訳ではありません。
マネージとネイティブとが、メモリ上で衝突しないようにする機能(メソッド等)が、豊富に用意されているので、それを活用すると言う意味です。
大雑把に説明しましたので、もう少し細かく説明しますと、以下の通りです。

------------

<Win32 EXE>では、普通にWin32 DLL を呼び出すのと同じように、<マネージ風Win32 DLL(共有DLL)>を呼び出すコードを記述する。

------------

<マネージ風Win32 DLL(共有DLL)>では、
(1)
複数のEXE間で、メモリ共有するネイティブコード(アンマネージコード)を記述する。
(2)
< Win32 EXE > から < C++/CLI で作るマネージEXE > をアクセスするインターフェイスをマネージコード(C++/CLIコード)で記述する。
(3)
< C++/CLI で作るマネージEXE > から < Win32 EXE > をアクセスするインターフェイスをマネージコード(C++/CLIコード)で記述する。

------------

<C++/CLI で作るマネージEXE>では、
(1)
目的のマネージ系機能(.NET系機能)を活用したコードを記述する。
(2)
<マネージ風Win32 DLL(共有DLL)>からのアクセスに対して、< C++/CLI で作るマネージEXE > のマネージ系データーをネイティブ系データーに変換して、<マネージ風Win32 DLL(共有DLL)>へデーター送信をする。
(3)
<マネージ風Win32 DLL(共有DLL)>からのアクセスに対して、< Win32 EXE > 側から来たネイティブ系データーをマネージ系データーに変換して、<C++/CLI で作るマネージEXE>でデーター受信をする。



====================================
[Win32 EXE で、.NET系機能を活用する方法 <最終ステップ>]
====================================

上記<ステップ3>で、「Win32 EXE で、.NET系機能を活用する」と言う目的を果たせています。
しかし、.NET系機能を活用したコードをC# で記述したい場合は、以下の構成になります。

構成図3
<Win32 EXE> --- <マネージ風Win32 DLL(共有DLL)> --- <C++/CLI で作るマネージDLL(インターフェイス用DLL)> --- <C# で作るマネージEXE>

説明は、<ステップ3>と殆ど同じで、<C# で作るマネージEXE>が増えただけです。



====================================
[C# をCOMコンポーネントにする手法]
====================================

まず、C# でDLL(クラスライブラリ)を作ります。
そのC# DLLで、「アセンブリを COM 参照可能にする」と言う設定を行ないます。
そうすると、C# DLLが、COM テクノロジーによるDLL としてエクスポート(機能の外部公開)されます。
COM テクノロジーとは、C++ を中心としたMicrosoft のテクノロジーのことです。
すなわち、Win32 EXE から、COM系DLL として、そのまま呼び出せます。
詳しくは、「アセンブリを COM 参照可能にする」のキーワードで検索して、情報を得て下さい。

構成図4-1
<Win32 EXE> --- <COM 風C# DLL>

ただし、この方法は、幾つかの問題点があります。
<COM 風C# DLL>の作成は、COM テクノロジーを知っている必要があります。
また、そのDLL を利用する側の<Win32 EXE>の作成も、COM テクノロジーを知っている必要があります。
すなわち、この方法は、COM プログラミングの経験者用の方法となります。
なお、今からCOM の勉強をするのならば、COM か、COM/DCOM と言う単語が題目に付いた本を購入します。
ATL と言う本でもよいです。
(ATL は、COM 系技術の内の一部の技術で、本件は、ATL 関連になります)
しかし、殆ど絶版で、中古本を高価な額で買うことになります。
また、上級者でも挫折者が沢山出た技術なので、本を買っても、挫折する確率が高いです。
なお、COM 関連の機能を極力簡単に改良したのがC# です。
よって、これからCOM を学ぶよりも、まるまる全てC# で作ったほうがよいと思います。
もしくは、前半で回答した方法(<ステップ3>か<最終ステップ>)のほうがよいと思います。
その他の問題としては、混合の問題です。
インターネット情報等のサンプルは、足し算関数などの簡単なサンプルを使っているので、

<Win32 EXE> --- <COM 風C# DLL>

になります。
しかし、実際は、.NET機能をがんがんと活用するので、混合の問題が出てきます。
よって、実際は、

構成図4-2
<Win32 EXE> --- <COM 風C++/CLI DLL> --- <C# DLL>

となり、間接的な度合いが、少しだけ深まってしまいます。

  • abi********さん

    2015/10/1709:45:53

    [結論]
    C# 系DLL をアンマネージ系(Win32 系 、又は、COM系)のDLLとして活用する方法は、上記の通り存在します。
    表現を言い換えれば、アンマネージ系(Win32 系 、又は、COM系)で、.NET系機能を活用する方法は、上記の通り存在します。
    しかし、質問でも言われているように、直接的ではなく、間接的な手法になります。
    しかも、かなり複雑で、かつ、難しくなります。


    [余談]
    「複雑で、かつ、難しい」と言いましたが、これでもかなり簡単になっています。
    一般のアプリケーション開発と言う意味では、難しいほうですが、インターフェイス作成の分野としては、かなり簡単なほうです。
    異なる環境間のインターフェイスを作成するには、まず、それぞれの環境の仕様(原理的仕様)を熟知する必要があります。
    そして、バイナリレベル(機械レベル)での変換機能をアセンブラやC言語(C++)を作成して行きます。
    しかし、---

    (続く)

  • その他の返信(1件)を表示

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

ベストアンサー以外の回答

1〜2件/2件中

並び替え:回答日時の
新しい順
|古い順

mon********さん

2015/10/1619:16:20

残念がらありません。
何故ならC#は基本的にManagedコードしか出力出来ないからです。
しかし、別途ツール(例えば.NET Nativeでコンパイル)を使用するとでコンパイル時に中間コードをネイティブコードに変換することはできます。
しかし、ネイティブではあるもののメモリ管理はされるため、Unmanagedではありません。

通常、このようなケースではC/C++でUnmanaged DLLを作成し、C++/CLIでラップしてC#から呼び出します。

ayu********さん

編集あり2015/10/1710:45:37

C#自体がCLRが前提の言語ですので、直接書く事は無理です。
アンマネージドコードはCかC++で書く事になりますね。

その上でC#から呼び出すのであれば、ラッパーを定義してCOM呼び出しするしか無いでしょう。
逆の、COMからC#コードを呼び出す事も可能です。
https://msdn.microsoft.com/ja-jp/library/ms173185.aspx

また、アンマネージドコードを書かねばならない理由にもよるのですが、、、
単純に他のアンマネージドコードとのインターフェース用で、構造体などのやり取りの事だけならC#側でマーシャリングでアンマネージドメモリにする事は可能です。

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる