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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

7352閲覧

C++/CLIのCOM公開について

hex

総合スコア7

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

3クリップ

投稿2018/03/26 15:50

###質問内容
C++/CLIで「C++(アンマネージ)、C#、VB」で参照できるCOMを作成する方法をご教示いただけませんでしょうか。
※ 関数およびクラス両方COM公開したいと考えております。
###余談
C++/CLIを使用しており、COM公開をしたいと考えております。C++/CLIを使用するのは初めてです。
C++/CLIを使用する理由は、C#のdllを使用するためです。
質問は、漠然とした内容で申し訳ございませんが、上記の通りです。

C++/CLIについての資料が少ないという点もありますが、自分自身が
COMについてや他一般的な情報についての知見がほぼないということ
が原因で、C++/CLIでCOM公開する方法を自力で調べることができておりません。
下記サイトを見て、COMについて少しは理解できたつもりでいたのですが、
C#などの.Netプログラミングでは勝手が違う?ようで、タイプライブラリ?や
アセンブリの指定?などあるようでして、、、C++でもある???勉強中です。

[連載! とことん VC++] 第 2 回 COM 再入門 ~ COM オブジェクトの基本的実装 ~
https://code.msdn.microsoft.com/VisualC-dbc36ad9/

それでも、C#などでは"COM登録"、"COM公開"などで調べると方法はすぐに
出てくるので、理屈はまだ理解できておりませんが、、、なんとかやり方だけ
はすぐに分かります。
サンプルなど、どこかに転がってはいないものでしょうか。
###確認したこと

  • C++(アンマネージ)と同じような手順でCOM登録

下記サイトのように、C++(アンマネージ)でするようなCOM登録を行うと、
CoInitializeEx(),CoCreateInstance()で、C++(アンマネージ)から参照
できることは確認できました。
※ C++/CLIでは、DLLエントリポイントなるDllMain()がないため、DllMain()の実装はしていないです。

[連載! とことん VC++] 第 2 回 COM 再入門 ~ COM オブジェクトの基本的実装 ~
https://code.msdn.microsoft.com/VisualC-dbc36ad9/

ただ、これではC#やVBから呼び出せません。
C#やVBからCOMコンポーネントを使用する場合、[参照の追加]-[COM]から、
使用したいCOMをプロジェクトの参照に追加する必要があると認識して
おります。ですが、上記のようなCOM登録の方法では、[参照の追加]-[COM]
の一覧の中に登録したCOMの情報は表示されません。

他のCOM登録されているDLLのレジストリを確認すると、以下のキーが登録
されていることを確認できたので、同様に追加したところ、
[参照の追加]-[COM]の一覧の中に作成したDLLが表示されることを確認できました。

※ (Clsid)と(TypeLibid)には実際のGUIDが入っていました。 HKEY_CLASSES_ROOT\CLSID\{(Clsid)}\TypeID @="(TypeLibid)" HKEY_CLASSES_ROOT\TypeLib\{(TypeLibid)} HKEY_CLASSES_ROOT\TypeLib\{(TypeLibid)}\1.0 HKEY_CLASSES_ROOT\TypeLib\{(TypeLibid)}\1.0\0 HKEY_CLASSES_ROOT\TypeLib\{(TypeLibid)}\1.0\0\win64 @="(dllのフルパス)" HKEY_CLASSES_ROOT\TypeLib\{TypeLibid}\1.0\FLAGS @="0" HKEY_CLASSES_ROOT\TypeLib\{TypeLibid}\1.0\HELPDIR @="(dllのパス)"

なお、実際に追加しようとすると、当該DLLはCOMコンポーネントではない旨の
エラーが発生し、追加できません。

  • C#っぽい?COM登録

下記URLは、私が望むものと一致していると考え、実際に試してみたの
ですが、「regasmにてDLLを登録」という部分で有効な.NETアセンブリ
ではないと怒られてつまずきました。ここがCOMについて知らないと
いけないんだろうなと勉強中です。

てんどん日記 [C++/CLI] COMのライブラリ公開
http://tendonmeister.at.webry.info/200902/article_1.html

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

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

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

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

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

KoichiSugiyama

2018/03/27 06:52

Visual Studioのバージョンはいくつでしょうか?最新のVSだとC++/CLIはあまり推奨されていないようなので、ちょっと前のバージョンの方が使いやすいかもしれません。
hex

2018/03/27 14:31 編集

ありがとうございます。バージョンは2015を使用してます。推奨されていない情報がどこかないか少し探したうえで、ちょっと前のバージョンのもので試してみようと思います。
mituha

2018/03/27 23:34

2010でC++/CLIのインテリセンスが効かない問題があったと思いますので、今(2015で)大丈夫ならそれより前に戻さないほうが良いかと思います。
mituha

2018/03/27 23:50

検索で例がすくないように、アプローチとして一般的でない可能性が高いです。C++部分がどのような種類なのか、呼び出したいC#がどんな機能なのかをもう少し詳細に書いたほうが回答がつきやすいかもしれません。
mituha

2018/03/27 23:57

あ、検索時は記事の日付にも注目したほうが良いです。古すぎる記事は気をつけたほうがよいですし、時系列を考慮して技術の変遷を追わないと無駄に古いやりかたになりかねません。
guest

回答3

0

ベストアンサー

C++/CLIのCOMを試して見ました。
COMとして使用可能ですが、C#からCOM参照しようとすると直接DLLを参照しろとエラーになりCOMとしては使用できません。
ですので、.NetアプリのみにDLLを提供したい場合はCOM登録する必要はありません。

一応こちらで試した手順を記載します。

C++/CLI
GUIDは適当に変更してください。

c++

1#pragma once 2 3using namespace System; 4using namespace System::Runtime::InteropServices; 5namespace ComSample { 6 [ComVisibleAttribute(true)] 7 [ClassInterfaceAttribute(ClassInterfaceType::AutoDispatch)] 8 [Guid("D226F6D4-15DD-449B-B20E-34A77F5516A2")] 9 public ref class Class1 10 { 11 public: 12 int TestFunc1(int x, int y) 13 { 14 return x + y; 15 } 16 }; 17} 18

上記をビルドした後regasmで登録を行う。
DLLがx86の場合
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe /codebase /tlb ComSample.dll
x64の場合
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe /codebase /tlb ComSample.dll

「regasmにてDLLを登録」という部分で有効な.NETアセンブリではないと怒られてつまずきました。

のエラーはregasmとDLLでx86/x64があっていないためだと思います。

JavaScriptから実行するコード

javascript

1var obj = new ActiveXObject("ComSample.Class1"); 2 3var result = obj.TestFunc1(1,2); 4 5WScript.Echo(result);

x64 OSではx64のwscript.exeで実行されるのでx64版のDLLでregasmが必要。
もしくはc:\windows\syswow64\wscript.exe
で実行する。

投稿2018/03/28 13:53

hmmm

総合スコア818

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

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

0

最近、COM(ActiveX)を使用することがないので、技術的な答えにはなっていませんが。

組み合わせ的には、C++(アンマネージ) から C# を使用する以外ではCOMの必要がありません。
C#、VB.net から C++/CLI は .NET としての参照で問題ないと思いますが、COMとして使用する理由がありますでしょうか?

投稿2018/03/27 00:23

mituha

総合スコア385

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

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

hex

2018/03/27 14:26

ご回答ありがとうございます。 > C#、VB.net から C++/CLI は .NET としての参照で問題ないと思いますが、COMとして使用する理由がありますでしょうか? COMとして使用したい理由は、マネージまたはアンマネージからでも呼び出すことができるため(できますよね?)となります。 公開する対象がC#など.Netプログラミングだけでしたら、.Netとしての参照で問題はなさそうです。ただ、C++も対象にしたいんです。
episteme

2018/03/27 20:16

nativeから使えるDLLをC/C++で書いて C++/CLIでそいつを呼ぶ.NETアセンブリ書きます僕なら。 これで双方から使えるし。
mituha

2018/03/27 23:41

そうですよね、想定される C++/CLI の使用方法は、C++のDLLを.NET で使用するためのラッパー。 ネイティブなC++からは直接使用。 C#のDLLをC++で使用するなら、C++/CLIを介さずに、C#のDLLをCOMとして登録。 C#からはC#のDLLを直接使用。 のパターンかと思います。 そもそも、.NETがCOMの置き換えとも言えるので、今敢えてCOMを使う理由と必要性は限られてくるかと。
naohiro19_

2018/03/28 04:52

Visual Studio のC++プロジェクトには「アセンブリをCOM参照可能にする」がありません。この項目があるのはF#/C#/VB.NETのみです。
mituha

2018/03/28 05:49

> naohiro19_ 「アセンブリをCOM参照可能にする」の設定は単にComVisible属性の有無を切り替えてるだけで、コンパイルオプションが変わるわけではないように思えます(未確認)。 なので、C++/CLIでもRegasmで登録さえすれば大丈夫だとは思います。 ネイティブなC++はそもそも、COM用のプロジェクト?(作りかた覚えてません)にすることになるかと。
guest

0

遅くなり申し訳ございません。
hmmmさんから頂いた回答に従うとC++/CLI(.Net)のDLLのCOM登録ができました。そして、その.Net(C#やらVB)で[参照の追加]で追加しようとすると『.NETアセンブリからエクスポートされましたが、参照として追加できません。.NETアセンブリへの参照を追加してください』というメッセージで拒否されました。
つまり、VisualStudioでは、.NetでCOM公開しているものを.Netで参照する場合、COM参照でなく直接.Net参照しろということであると認識しました。Microsoftの公式なページのどこかに記述があれば、うれしいのですが、見つかりませんでした。。。ただ、「C#でCOM公開したが、COM参照できず直接.Net参照した」という記事はちらほらとあったため、これで納得しています。
※ タイプライブラリは、.NetだけでなくCOMにもあるんですね(〃∇〃)
※ 存在や意義を知らず、作成しておりませんでした。
※ .Netの場合、RegAsm.exeの/tlbオプションで勝手に作ってくれると認識しました。

そのため、mihutaさんから頂いているように.Netから呼び出すときは直接参照し、unmanageからはCOMとすればよいのかなと思いました。
上とは別に、manage/unmanage両方から同じように参照できるクラス/メソッドなどを一つのDLLから提供したい場合は、以下のような感じぐらいしかなさそうですね。


①C# dll(COM) => C++ dll(COM)
or
②C# dll(.Net) => C++/CLI ラッパーdll => C++ dll(COM)


①は、dllは二つで済みますが、引数の型など考慮する部分が多そうです。
②は、dllが三つになり、修正が入ったときに手間が掛かりそうです。

具体的にどのように対応するか決めておりませんが、ご回答をいただき整理ができそうです。
ご回答、コメントを頂いた皆さん、ありがとうございました。

投稿2018/04/02 00:56

編集2018/04/02 00:59
hex

総合スコア7

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問