C++関数からCの関数を呼ぶには extern "C" を使うのはわかるのですが
C関数からC++の関数を呼ぶ方法がわかりません。
『外部参照 1 が未解決』になってリンクが出来ません。

ちなみにC++の関数はDLLで、他のC++関数からは呼ぶことも実行出来ることも
確認済みです。

よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (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;
}
    • good
    • 0
この回答へのお礼

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

お礼日時:2001/10/17 09:00

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QC++ の typedef の 使い方の質問

C++のtypedefの使い方の質問ですが、typedefは、別名の定義として、知られていますが。
以下のソースの意味がよく読み取れないです。windows プログラミングとC++
が分かるかたがいれば、以下のソースの意味を教えていただきたいです。

よろしくお願いします。
typedef BOOL (WINAPI *AddAccessAllowedAceFn)(
PACL pAcl,
DWORD dwAceRevision,
DWORD AceFlags,
DWORD AccessMask,
PSID pSid
);

Aベストアンサー

関数ポインタの別名定義です。
「関数ポインタ typedef」をキーワードにWeb検索してみてください。
丁寧に解説されているサイトが見つかるでしょう。

QC++の関数をCで呼ぶには??

C++の関数をCで呼ぶには、「extern C」を使用することが有名だと思いますが、これだとC++で記述したソースコードにextern Cを追加することにあると思います。
では、C++のほうはまったく手をつけず、C++の関数をCで呼ぶことは可能なのでしょうか?
知っている方がいましたらよろしくお願い致します。

Aベストアンサー

一般的には不可能です。既存のC++コードを修正することなく、Cから呼び出すには、

extern "C++" void f();

extern "C" int call_f() throw()
{
 try
 {
  f();
 }
 catch (...)
 {
  return -1;
 }
 return 0;
}

のようなラッパー関数を作り、それを呼び出す必要があります。

なお、C++の関数のマングル名を調べて強引に呼び出すことも、場合によっては可能ですが、処理系によってはC++結合とC結合のコーリングコンベンションが異なる場合があるので要注意です。また、仮に問題なく呼び出せたとしても、C++の関数から送出された例外を処理することができませんので、破綻するのは目に見えています。

QC++.NET の String型の使い方

初めて質問いたします。
C++ .NET 2005 Express Beta版を入手し、Windows Formsのプログラミングを勉強してます。

TextBoxのTextに値を変数で指定したいのですがどうすれば良いのかわかりません。

  textBox1->Text = "Test";
とダイレクトに値を指定すればできるのですが、

  #include <string>
  using namespace std;
   (省略)
  string str = "Test";
  textBox1->Text = str;
は、エラーになってしまいます。

C++標準のstringクラスではなく、.NETはStringクラスがあるようですが、これの使い方がMSDN等で調べているのですが分かりません。
分かりやすいURLなどありましたら教えていただけませんか。

Aベストアンサー

textBox1->Text = new String(str.c_str());
でいけるんじゃないかなあ。
試してないのでなんですが、
C++のstringクラスからは、c_str()で、いわゆるNULL終端文字列へのポインタが得られて
.NETのStringクラスは、NULL終端文字列でのコンストラクタがありますから。

Qc++,ある関数のクラスから別のクラスの関数を呼ぶ

c++で、あるクラスのメンバ関数から、別のクラスのメンバ関すを呼びたいのですが、どのようにしたらできますか?
例えば、以下のような単純なコードを考えています。やりたいことは、Aのメンバ関数であるaaa()からBのクラスであるbbb()を呼びたいと思っています。その理由を少し説明します。ここでは、Aというクラスとmain関数はオープンソースコードを例えています。できるだけ、元のオープンソースコードを書き換えずに新たな機能を拡張したいと思っています。そこで、Bというクラスを使って、元のオープンソースコードに機能を拡張しようとしています。このような理由なので、bbb()という関数はaaa()という関数から呼びたいです。メイン関数には何も書き加えないのがベストです。
現状では、実行すると「this is aaa」という出力しか出ません。ここに「this is bbb」の出力を加えたいです。クラスAとBにある程度コマンドを追加して、解決できないでしょうか。

#include <iostream>
using namespace std;

//------------------------------------------------------
class A{
public:
void aaa();
virtual void bbb(){}
};
//------------------------------------------------------

//------------------------------------------------------
class B : public A{
public:
void bbb();
};
//------------------------------------------------------

//------------------------------------------------------
void A::aaa()
{
cout << "this is aaa \n";
bbb();
}
//------------------------------------------------------

//------------------------------------------------------
void B::bbb()
{
cout << "this is bbb \n";
}
//------------------------------------------------------

//------------------------------------------------------
int main()
{
A a;
a.aaa();
return 0;
}
//------------------------------------------------------

c++で、あるクラスのメンバ関数から、別のクラスのメンバ関すを呼びたいのですが、どのようにしたらできますか?
例えば、以下のような単純なコードを考えています。やりたいことは、Aのメンバ関数であるaaa()からBのクラスであるbbb()を呼びたいと思っています。その理由を少し説明します。ここでは、Aというクラスとmain関数はオープンソースコードを例えています。できるだけ、元のオープンソースコードを書き換えずに新たな機能を拡張したいと思っています。そこで、Bというクラスを使って、元のオープンソー...続きを読む

Aベストアンサー

Aを極力触りたくないのであれば、あまりカッコよくありませんが、AがBを継承するではどうでしょうか?
提示コードを以下のように書き換えれば、とりあえず期待する動きはすると思います。

//------------------------------------------------------
class B {
public:
virtualvoid bbb();
};
//------------------------------------------------------

//------------------------------------------------------
class A: public B{
public:
void aaa();
};
//------------------------------------------------------
※ その他はそのまま

Qc++ stringの使い方

お世話になります。
最近c++始めました。
stringの使い方がよくわかりません。
以下のstringの使い方が問題ないか確認頂けますか。
スマホで書くため、文法が合ってないと思いますが、stringの使い方だけ確認させてください。
引数にstringで囲って渡すのは実装として普通行いますか。
やってはいけないですか。
是非ご教示ください。

#define STR1 "mojiretu"
main()
if(check(string(STR1)))



bool check(string str)

Aベストアンサー

間違っちゃいないけど、直に const string でかまわんのでは?

#include <iostream>
#include <string>

const std::string STR1 = "mojiretu";

bool even_length(const std::string& str) {
return str.length() % 2 == 0;
}

int main() {
if ( even_length(STR1) ) {
std::cout << STR1 << " : even\n";
} else {
std::cout << STR1 << " : odd\n";
}
}

QC++のクラスで継承先の仮想関数をコンストラクタで呼ぶ方法について

タイトルのとおり、C++のクラスで自分のクラスを継承した先の仮想関数をコンストラクタで呼ぶ方法についてなんですが、これは呼ぶことができないのが常識ですよね。
なのですが、いろいろとやってみたところ、制限はあるものの、なんとかそれっぽいのが作れたんです。
しかし、本当にこのコードが間違ったことをしていないという自信がありません……。
そこで皆さんにお訊ねします。
このコードはセーフでしょうか?アウトでしょうか?

//----- ここから -----

#include <iostream>
struct CLS{
virtual void func()=0;
CLS(){}
template<class T> CLS(T*){reinterpret_cast<T*>(this)->T::func();}
};

struct CLS1:public CLS{
virtual void func(){ std::cout << "x";}
CLS1():CLS((CLS1*)0){}
template<class T> CLS1(T* x):CLS((T*)0){}
};

struct CLS2:public CLS1{
virtual void func(){}
CLS2():CLS1((CLS2*)0){std::cout<<"y";}
template<class T> CLS2(T*):CLS1((T*)0){}
};


int main(){
CLS* x = new CLS1;
CLS* y = new CLS2;
delete x;
delete y;
return 0;
}

//----- ここまで -----

C++の言語規約を読んだりとかはしていないので、自分では判断つきかねるのですが、コンパイラを通したところ、
cl g++ dmc bcc32
あたりで試して全て成功しています。(どのコンパイラでも、ということになるのかはわかりませんが。)
セーフかアウトか…、またその理由をお聞かせください。
暇なときでかまわないので、ご意見いただけたらと思います。

タイトルのとおり、C++のクラスで自分のクラスを継承した先の仮想関数をコンストラクタで呼ぶ方法についてなんですが、これは呼ぶことができないのが常識ですよね。
なのですが、いろいろとやってみたところ、制限はあるものの、なんとかそれっぽいのが作れたんです。
しかし、本当にこのコードが間違ったことをしていないという自信がありません……。
そこで皆さんにお訊ねします。
このコードはセーフでしょうか?アウトでしょうか?

//----- ここから -----

#include <iostream>
struct CLS{
virtua...続きを読む

Aベストアンサー

私も他の方と同様、「アウト」だと思います。

ISO/IEC14882だと12.7あたりで初期化完了してない云々に触れてます。
このコードはundefined behavior(未定義動作)なのでコンパイラにはエラーを検出する責務がありません。
# 当然、どのコンパイラでもそうなる保証なんてないですし、
# エラーを見つけてくれるとも限りません。(だからとりあえずそれっぽく動いて見えている)

実際、上記のコードをちょっと直して、問題をおこすのも簡単です。

 各クラスにメンバ変数を追加して、出力してみてください。

未定義動作として不正参照してるだけで初期化が完了してませんので、
単純に文字を出力してるだけだと気づかないかもしれませんが、
例えば手元のVC7.1で以下のコードを実行するとx,yともn1、n2がゴミになります。
これがご期待の動作でしょうか。(意図してメンバを参照しないコードを書いていますか?)
提示のサンプルはまだしも、未定義動作で言語仕様から逸脱した挙句に、
実際にはメンバすら触れないメソッドの呼び出しは何かうれしいですか?と私は思います。

また、reinterpret_castはポインタを補正をしてくれませんので、
仮想継承とかしてる場合はもっと致命的におかしなことになる可能性があります。
(これも意図して避けていますか?考慮されていないだけですか?)

まぁ、それでもundefined behaviorなので一見正しく動く環境はあるのかもしれませんが、
私ならやはり「アウト」だといいます。

#include <iostream>
struct CLS{
int n1;
virtual void func()=0;
CLS():n1(1){}
template<class T> CLS(T*){reinterpret_cast<T*>(this)->T::func();}
};

struct CLS1:public CLS{
int n2;
virtual void func(){ std::cout << "x" << n1 << ":" << n2<< std::endl;}
CLS1():CLS((CLS1*)0), n2(2){}
template<class T> CLS1(T* x):CLS((T*)0){}
};

struct CLS2:public CLS1{
int n3;
virtual void func(){}
CLS2():CLS1((CLS2*)0), n3(3){std::cout<< "y" << n1 << ":" << n2 << ":" << n3 << std::endl;}
template<class T> CLS2(T*):CLS1((T*)0){}
};


int main(){
CLS* x = new CLS1;
CLS* y = new CLS2;
delete x;
delete y;
return 0;
}

ちなみに、初期化順はもともとが記述順とは別に決まっているものなので、
仮にn3(3)等を前に書くとかしても無駄です。
# undefined behaviorなので「VC7.1で試しても変わりませんでした」が正しいか。

私も他の方と同様、「アウト」だと思います。

ISO/IEC14882だと12.7あたりで初期化完了してない云々に触れてます。
このコードはundefined behavior(未定義動作)なのでコンパイラにはエラーを検出する責務がありません。
# 当然、どのコンパイラでもそうなる保証なんてないですし、
# エラーを見つけてくれるとも限りません。(だからとりあえずそれっぽく動いて見えている)

実際、上記のコードをちょっと直して、問題をおこすのも簡単です。

 各クラスにメンバ変数を追加して、出力してみてください...続きを読む

QVisial C++おけるπの使い方

自宅でCプログラミングの練習をするためVisial C++ 2008を使って
プログラムをしています。y<sin(πx)となった時の
割合などを計算するプログラムで                「M_PIが定義されていない識別子です」
とでてきます。所持している本を参考にしてもM_PI=πとして用いる
と書いてあり、math.hもインクルードしてるので原因が分からなくて
困ってます。Visial c++ではπの使い方には何か別の使い方がある
のでしょうか?よろしくお願いします。
*↓が実際に作ったプログラムです。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int main(void){
int i,n,count=0;
double x,y,r,error;

srand((unsigned)time(NULL)); /*乱数の初期化*/

printf("How many trials?");
scanf("&d",&n);

for(i=0;i<n;i++){
x=rand()/(RAND_MAX+1.0);
y=rand()/(RAND_MAX+1.0);

if(y<sin(M_PI*x)){
count++;
}
}

r=(double)count/n; /*キャスト演算子を使用*/
error=2/M_PI-r;

printf("Result is %f (Error: %f)\n",r,error);

return 0;
}

自宅でCプログラミングの練習をするためVisial C++ 2008を使って
プログラムをしています。y<sin(πx)となった時の
割合などを計算するプログラムで                「M_PIが定義されていない識別子です」
とでてきます。所持している本を参考にしてもM_PI=πとして用いる
と書いてあり、math.hもインクルードしてるので原因が分からなくて
困ってます。Visial c++ではπの使い方には何か別の使い方がある
のでしょうか?よろしくお願いします。
*↓が実際に作ったプログラムです。
#include ...続きを読む

Aベストアンサー

★アドバイス
・math.hをインクルードする前に『_USE_MATH_DEFINES』定数を define します。

#define _USE_MATH_DEFINES
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int main( void )
{
 :
 return 0;
}
必ず include する前に定義して下さい。

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

VC++2008 Expressを使っています。
c++からdll内の関数を呼ぶ記述方法が知りたいです。

hoge.dllの関数
int test(int x);

c++
??????????

Aベストアンサー

手順としてはこんな感じになります。


// 関数の型宣言
typedef int (*PFUNC_TEST)(int);

// DLLをロード
HINSTANCE hDll = LoadLibrary("hoge.dll");

// 関数へのポインタを取り出す
PFUNC_TEST test = (PFUNC_TEST)GetProcAddress(hDll , "test");

// 関数を使う
int a = test(5);

// 最後にDLLを解放
FreeLibrary(hDll);


LoadLibrary関数とGetProcAddress関数は失敗するとNULLを返すので、そのチェックも必要です。

QcygwinでのC++の使い方

cygwinでC言語で書いたプログラムを実行したいのですがcygwinを起動すると
私の名前@なにやらアルファベット
が表示され次の行に

と表示されるんですがこの後にどんなことを書けば
#include<・・・>
としてC++のプログラムを書いていくことができるんですか?そもそもcygwinの使い方が根本的に違うんですかねえ?それともメモ帳かなんかにプログラムを書き保存しそれをcygwinで実行するんですかねえ?とりあえずプログラムを実行できるようにしてください。おねがいします。

Aベストアンサー

> それともメモ帳かなんかにプログラムを書き保存しそれをcygwinで実行するんですかねえ?

おおむねその通りです。

メモ帳でも何でもよいので、エディタでソースファイルを作成してください。作成したソースファイルは、とりあえずホームディレクトリに格納するとよいでしょう(C:\cygwinにCygwinをインストールしたのであれば、C:\cygwin\home\アカウント名がホームディレクトリになります)。

作成したソースファイルがfoo.cppだった場合、

g++ foo.cpp

とすれば、a.exeという実行ファイルが同じディレクトリにできるはずです。そこで、

./a

と入力すれば、a.exeを実行することができます。

QC&C++からC#のexeを呼ぶ方法

いつもお世話になっております。

環境
Windows VISTA SP1
Visual Studio 2008

疑問
C(C++)からC#で作られたexeを呼ぶ方法がわかりません。
ret = CreateProcess(NULL,Common_Data->exename,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi);

の様にCreateProcessではexeを呼べません。
(Common_Data->exenameにはGetCurrentDirectory使って
絶対パス指定してます)

おそらくC#でつくったプロジェクトの設定を変えてビルド
する必要があると推測していますが
どうすればいいのかわからないです。

以上 よろしくお願いいたします。

Aベストアンサー

「CreateProcess error 998 ERROR_NOACCESS」
でぐぐってみたところ、以下のような情報がありました。
http://fujiyoshisyouta.blog72.fc2.com/blog-entry-209.html

STARTUPINFO構造体(si)は、正しく初期化してますか?
特に、si.cbにSTARTUPINFO構造体のサイズが正しく入っていないと、
今回のようなエラーを返却する可能性が高いと思います。

http://itpro.nikkeibp.co.jp/article/COLUMN/20070126/259762/
を参考にしてください。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング