• ベストアンサー

Cの関数からC++の関数(DLL)を呼ぶ方法について

C++関数からCの関数を呼ぶには extern "C" を使うのはわかるのですが C関数からC++の関数を呼ぶ方法がわかりません。 『外部参照 1 が未解決』になってリンクが出来ません。 ちなみにC++の関数はDLLで、他のC++関数からは呼ぶことも実行出来ることも 確認済みです。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.1

基本的に、呼ぶことができません。と言うのも、c++ には、関数のオーバーロードと 言う機能があって、同じ関数名でも、引数の並び(型や個数)が違うと別の関数として 扱われます。 この機能は c にはありませんから、たとえひとつしかその名前の関数を書いてなくても オーバーロードの仕組みを持った関数になるわけですから、それは c から呼ぶことは できません。 > C++関数からCの関数を呼ぶには extern "C" を使うのはわかる 正確には、そうじゃないんです。 c++ は、型のチェックが厳密ですから、関数を呼ぶ場合には、そのプロトタイプ宣言が 必須です。 普通に書くと、c の関数なのか、c++ の関数なのかの区別が付かないので、c の 関数なんだよ、と宣言をするのが extern "C" なんです。 で、本題に戻って、「c++ で記述した関数を c から呼ぶには?」ということなの ですが、答えは「extern "C" で宣言をした、c++ の関数を作る」ということに なります。 例えば、以下の関数は思いっきり c++ で記述した関数ですから、関数自体は c++ じゃないとコンパイルできませんが、c から呼ぶことが可能です。 ★ヘッダ #ifdef __cplusplus extern "C" { #endif void print_string(char*); #ifdef __cplusplus } #endif ★ソース #include "ヘッダファイル" #include <iostream.h> void print_string(char* str) { cout << str << endl; }

y_panda
質問者

お礼

早速の回答ありがとうございました。 例示もあってとても助かりました。 これを参考にプログラムを修正します。 突然プロトタイプの担当者に指名されて パニック状態なので本当に助かりました。 ありがとうございます。

関連するQ&A

  • Cで作成したDLLからC++内で関数を利用する。

    こんにちは。 Cで作成したDLLをC++で呼び出してその関数を使いたいのですが、リンクがうまくいきません。 externを使えばいいのですか?? 具体的な使い方が分からないので、教えてください。

  • C#からC++のDLLを使いたい時

    C#からC++(unmanaged)のDLLを使いたい時、 DLLをどのように参照すればよいのでしょうか。 [DllImport("名前.dll")] extern static double 関数名(); という指定は分かるのですが、 それだけじゃもちろん、 「DLL (名前.dll) を読み込めません。」 ってなりますよね・・・。

  • CファイルとCPPファイルのDLL作成

    CファイルとCPPファイルを同一DLLに取り込むことは可能でしょうか?もし可能であれば実現方法も教えて頂きたいのですが。 現状は別DLLを作成しているのですが、両ファイルを取り込んでビルドすると外部関数宣言をしている箇所がエラーになってしまいます。(extern "C"の箇所が・・・)

  • VC#からdll関数を使う

    c#(vs2003)から、c++で書かれたdllの中に含まれる関数を読み込む部分を書いています。この関数は以下のように定義 され、構造体のポインタを返り値として返します。 SENSOR* GetSensor(); SENSOR構造体はdllの中では以下のように定義されています。 typedef struct{   int type; unsigned short param; char name[64]; DWORD con_pos; } SENSOR; これをc#のコードの中で読み込むため、c#のクラスの中で、以下のように再定義しました。 [StructLayout(LayoutKind.Sequential)] public struct SENSOR {   public int type;   public ushort param;   public string name;   public uint con_pos; } 後にc#のコードの中に、dllの中の関数を呼び出す定義を以下のように書きました。 [DllImport("sensor.dll"); public static extern SENSOR* GetSensor(); ここで SENSOR* sensor = GetSensor(); といった感じでdllをの関数を使って値を取得するようにしたのですが、実行すると 「return value をマーシャル できません : ポインタはマーシャルされた構造体を参照できません。」 といったエラーが出ます。いろいろと調べたのですが解決方法がわかりません。アドバイスをいただけたら幸いです。

  • Visual studio c++ dll作成時のエラー

    c初心者です。 ユーザーからもらったaaa.dllにある関数Calc_UL(struct型)をコールするbbb.dllを作成しようしています。 コンパイルはとおるのですが、 dllのビルドがうまくいきません。ユーザーからはaaa.dllとaaa.libとaaa.hだけもらっており、aaa.libにはリンク設定をしています。 bbb.obj : error LNK2001: 外部シンボル ""int __stdcall Calc_UL(struct ULData *)" (?Calc_UL@@YGHPAUULData@@@Z)" は未解決です Debug/bbb.dll : fatal error LNK1120: 外部参照 1 が未解決です。 link.exe の実行エラー aaa.dllを指定するところが特に無いのですが、どこかで指定しないといけないのでしょうか? よろしくお願いします。

  • VCで作成したDLLをBCBから呼び出す方法

    皆さん こんにちは。 VCで作成したCのAPIを実装したDLLをBCB6.0で作成したアプリケーションから呼び出そうとしています。 コンパイルは通るのですが、リンク時に以下のエラーメッセージが表示されてしまいます。   [リンカ エラー] 外部シンボル 'My Function' が未解決(C:\BCB\***.OBJ が参照) BCB6のフォームプロジェクトからDLLを利用するために、以下の手順を行いました。 (1)DLLをbcb用に変換する   implib -a aaa.lib aaa.dll (2)プロジェクトにaaa.libを追加 (3)aaa.dllをプロジェクトのフォルダに追加 (4)コードを以下のように実装しました    extern "C" __stdcall ulong SysInitialize(void);  //プロトタイプ宣言    ulong ulRetVal = SysInitialize(); //コード内での呼び出し この状態でコンパイルは通るのですがリンカでエラーが発生します      [リンカ エラー] 外部シンボル 'SysInitialize' が未解決(C:\BCB\TELIGEV\MAINDLG.OBJ が参照 他のサイトで調べたところ、C++特有の修飾子"@***"がついている場合に同じエラーが出るとのことだったので、dumpbin.exeを使ってDLL内の関数をダンプしたところ、関数名にはアンダースコアや@などは関数名についていないようです。 dumpbinの出力結果   1 1D 000065A0 SysInitialize このほか、自分なりに調べたところ、以下のサイトを見つけたのですが、英語力の弱さから解決策を見出すまでには至りませんでした。 Using Visual C++ DLLs with C++Builder http://bcbjournal.org/articles/vol4/0012/Using_Visual_C_DLLs_with_CBuilder.htm どなたか、ご助言いただけると助かります。 よろしくお願いします。

  • C++で作ったDLLをC#で使うには?

    C#でC++で書いたDLLを使いたいと思っていますが、可能でしょうか? 本で調べてみると出来ると思って挑戦しています。 public class Form1 : System.Windows.Forms.Form { [DllImport("test.dll")] public static extern long abc(); ..... と宣言し、使う時には long a = abc(); としています。 しかし、いざデバッグして実行してみると、エントリポイントが見つかりません。と表示されてしまいます。 (そもそもDLLが使えるのならばですが)できればC#でC++のDLLが使いたいため、詳しい方ご教授願います。

  • DLL内からの外部変数の参照

    BCC(フリーコンパイラ)で、WindowsAPIを使った プログラムを作成しています。その過程で、DLLを 作成しているのですが、 test.c を、 bcc32 -WD test.c とし、test.dllを作成しました。 さらにそれを、 implib test.lib test.dll で、test.libを作成ました。 ところが、おなじtest.cファイルで、ほかのファイル の変数を参照しようとして、extern HWND hWnd と書き加えたところ、bcc32 -WD で、参照先が見つか らないというエラーが起こり、DLLが作成できなく なってしまいました。 DLL内から外部の変数を参照するにはどうしたらよいで しょうか。この場合の外部の変数というのは、WinMain 関数のあるmain.cファイル内の静的変数です。 よろしくお願いいたします。

  • c++からdll内の関数を呼ぶ記述方法が知りたいです。

    VC++2008 Expressを使っています。 c++からdll内の関数を呼ぶ記述方法が知りたいです。 hoge.dllの関数 int test(int x); c++ ??????????

  • C#から、C++作成dll内の関数を呼び出す方法

    C#から、C++で作成したdll内の関数を呼び出す方法は、以下の方法で実現できました。(メッセージボックスで "10" が表示されました) [C++側のヘッダファイル] #ifdef CPPDLL_EXPORTS #define CPPDLL_API __declspec(dllexport) #else #define CPPDLL_API __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ CPPDLL_API int fnCppDll(); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ [C++側のソースファイル] CPPDLL_API int fnCppDll() { return 10; } [C#側] using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApp1 { public partial class Form1 : Form { [DllImport("CppDll.dll")] public static extern int fnCppDll(); public Form1() { InitializeComponent(); } private void buttonGo_Click(object sender, EventArgs e) { int n = fnCppDll(); MessageBox.Show(n.ToString()); } } } 今回お聞きしたいのは、int型ではなく、C++側で型を定義されたクラスのオブジェクト(の参照)を返す関数を、C#側から呼び出し、それをどうやってC#で受け取るかを教えていただきたいのです。 具体的には以下のように実装してみました。 [C++側のヘッダファイル] #ifdef CPPDLL_EXPORTS #define CPPDLL_API __declspec(dllexport) #else #define CPPDLL_API __declspec(dllimport) #endif class CPPDLL_API CCppDll { public: int data; CCppDll(void); }; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ CPPDLL_API CCppDll& fnCppDll(); // C#が参照渡しということで、参照を返すようにした。 #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ [C++側のソースファイル] CPPDLL_API CCppDll& fnCppDll() { CCppDll* a = new CCppDll(); return *a; } CCppDll::CCppDll() : data(11) // メンバーは 11 で初期化 { } [C#側] using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApp1 { // ビルドエラーが起きるないように、とりあえず、C++と同じ(ような)クラスを定義 public class CCppDll { public int data; } public partial class Form1 : Form { [DllImport("CppDll.dll")] public static extern CCppDll fnCppDll(); public Form1() { InitializeComponent(); } private void buttonGo_Click(object sender, EventArgs e) { int n; CCppDll cls = fnCppDll(); // ※ n = cls.data; MessageBox.Show(n.ToString()); } private void buttonCancel_Click(object sender, EventArgs e) { Close(); } } } 実装しながらも、「これじゃあ、ダメだろうな。いかにもダメだな」と思った通り、上の※の部分で以下の例外が発生しました。 ------- 例外(ここから) ------- マネージド デバッグ アシスタント 'FatalExecutionEngineError' : 'ランタイムの重大なエラーが発生しました。エラーのアドレスは 0xcc9ff5a2、スレッド 0x36c8 です。エラー コードは 0xc0000005 です。これは CLR のバグであるか、またはユーザー コードのアンセーフまたは確認不可能な部分にバグがある可能性があります。このバグの一般的な原因には、スタックが壊れる可能性のある COM-interop または PInvoke のユーザー マーシャリング エラーが含まれています。' ------- 例外(ここまで) ------- 明らかに基本的なことが分かっていないことから起因するエラーと思われますが、具体的にどう実装すれば、正常に動きますか。(メッセージボックスで "11" を表示) よろしくお願いします。

専門家に質問してみよう