• 締切済み

二重定義の回避法

VCで1つのDLL内に2つの関数を持つDLLを作成しています。 簡単に書きますと次のようなコードになっています プログラムA #include "common.c" void abc{ ・・・ } プログラムB #include "common.c" void def{ ・・・ } これでビルドするとコンパイルは通りますが リンクのときに同じ関数名が2つ存在するという旨のエラーになります。 common.cの中にある関数がabeとdefの両方で使われているときだけ発生しますので エラーの原因は明らかなのですが、この回避方法が分かりません。 気休めにプログラムBの#includeを外してみたり(コンパイルエラーになります) common.cに#pragma onceを追記してみましたがダメでした。

みんなの回答

  • rentahero
  • ベストアンサー率53% (182/342)
回答No.3

#2の回答に横から補足 なんとなくグローバル変数もあるような気がする 関数をstaticにする(内部結合にする)場合、変数も共有したくないハズなので、グローバル変数もstaticにして(ファイルグローバル変数にして)ください。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

既に回答にあるように、プロトタイプだけを切り出したヘッダを用意するのが正攻法です。 他の方法としては、 ・関数にstaticを付けて内部結合にする。 ・マクロにする。 ・インライン関数にする。(Cの場合は移植性がなくなる) ・テンプレートにする。(C++のみ) ・無名名前空間を使う。(C++のみ) といった方法があります。 どうしても関数の実体が2つ必要な場合は、staticを付けるか無名名前空間にするのが一番無難です。

hawkwind
質問者

お礼

色々と方法論を挙げて頂き、感謝します。 今回は共通で使う関数の実体は1つにしたいけれど、 EXPORTする関数が2つある場合にどうしたらよいのかでした。 #1に具体的な解決策を書いておきました。

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.1

common.hの内容 #pragma once void funccommon(); common.cの内容 void funccommon(){ printf("test"); } プログラムA a.cの内容 #include "common.h" void abc{ ・・・ } プログラムB b.cの内容 #include "common.h" void def{ ・・・ } としてください。

hawkwind
質問者

お礼

sha-girlさん、画像処理のときはお世話になりました。 問題はcommon.cをincludeするのではなく、 common.cをコンパイルして1つのobjとすることで解決しました。 (それ以外にもう一点クリアする問題があって大変でした) その過程でsha-gielさんの勧告に従いまして ヘッダーファイルに型宣言をすることに致しました。 どうもありがとうございました。

関連するQ&A

  • DLL作成時、defファイルを使いたくない

    また質問させて下さい。 Visual Studio2005でDLLを使ったプログラムを作ろうとしています。 defファイルを利用すると、そのDLLファイルを作成できるのですが、 __declspec(dllexport)を利用すると、DLLファイルのその関数を読めなくなってしまいます。 なぜでしょうか? 下記は、MFCで、dll_test7というプロジェクトを作り、そのdll_test7.hのコードのすぐ下に その関数を書きました。(これがダメだと思うのですが…) //●Visual Studioのプロジェクト作成で、生成される部分 // dll_test7.h : dll_test7.DLL のメイン ヘッダー ファイル // #pragma once __declspec(dllexport) void __cdecl test0(void); #ifndef __AFXWIN_H__ #error "PCH に対してこのファイルをインクルードする前に 'stdafx.h' をインクルードしてください" #endif #include "resource.h" // メイン シンボル // Cdll_test7App // このクラスの実装に関しては dll_test7.cpp を参照してください。 // class Cdll_test7App : public CWinApp { public: Cdll_test7App(); // オーバーライド public: virtual BOOL InitInstance(); DECLARE_MESSAGE_MAP() }; //■作成した関数 __declspec(dllexport) void __cdecl test0(void) { CString cs; cs="aa"; ::AfxMessageBox(cs); } 上記は、defファイルを利用するとこの関数を呼び出せます。 以上、どうぞよろしくお願い致します。

  • PHPの関数の二重定義を防ぐには?

    phpでオリジナルの関数を作成したとき プログラムのミス等で、二度定義されてしまった時 Fatal error: Cannot redeclare というような、エラーが出ますが、include_onceのonceみたいな これを、出さぬよう、定義側で一度しか定義させないように するようにはできないのでしょうか? if($flag){   function hoge(){} } $flag = 1 のようにフラグを立てるしかないのでしょうか?

    • ベストアンサー
    • PHP
  • 相互のインクルードファイルの方法について

    下のように、2つのヘッダーファイルを相互にインクルードすると colorparettewindowclass.h(2) : fatal error C1014: インクルード ファイルが多すぎます : 深さ = 1024 というエラーが表示されます。(2つ表示される) 一応、#pragma onceを使用していますが、 エラーになります。 どうすればいいでしょうか? よろしくお願いします。 --------------------------------------------- <<ColorParetteWindowParentClass.h>> #include"WindowBaseClass.h" #include"ColorParetteWindowClass.h" #include"ColorClass.h" #pragma once class ColorParetteWindowParentClass : public WindowBaseClass { ((処理関数等定義)) }; --------------------------------------------- <<ColorParetteWindowClass .h>> #include"WindowBaseClass.h" #include"ColorParetteWindowParentClass.h" #pragma once class ColorParetteWindowClass : public WindowBaseClass { ((処理関数等定義)) };

  • 関数の実体定義にヘッダファイルの2重定義防止方法が効かない?

    いつもお世話になっています。 MFCでCプログラミングをしています。 ヘッダファイルの2重定義防止のために、 ヘッダファイル全体を下記のように 囲みました。 <aaa.h> #ifndef AAA #define AAA #define PI 3.141592 void Func(); int wa(int a, int b){ return a+b; } #endif ビルドしたところ、 関数宣言(Func)や#define部分(PI)については、 2重定義が防止されているようなのですが、 関数の実体部分(関数wa)については、 2重定義防止機能が働かず、 ***.obj : error LNK2005: "int __cdecl wa(int a, int b)" は既に ***.obj で定義されています。 というリンクエラーが表示されます。 関数の種類や ヘッダファイル内の宣言の順番を いろいろ変えてみたのですが同じ結果でした。 ここで、このヘッダファイルの先頭に #pragma onceを使用すると このリンクエラーは回避されるのですが、 他コンパイラとの互換性の観点から、 #pragma once以外の方法で実現する必要があるので、 困っています。 URLを検索してみたのですが、 このような特殊な場合について記述されているものは 見つけられませんでした。 どなたか解決法又はヒントをご教示頂ければ ありがたいです。 よろしくお願いします。

  • typedef定義型を使った関数について

    はじめて質問させていただきます。 Visual C++ 2008 Express Editionを使ってC言語のソースコードを記述しています。 (OSはWindows XPを使用しています。) ビルドを行った際に以下のエラーが発生していて、先に進めません。 色々と調べてみたのですが、解決方法がわからず質問させていただいた次第です。 解決方法についてご存知の方がいらっしゃいましたら、回答いただけると嬉しいです。 ■エラー内容 ------ ビルド開始: プロジェクト: Sample, 構成: Debug Win32 ------ コンパイルしています... Sample.c d:\sample\sample\Sample.c(4) : error C2061: 構文エラー : 識別子 'GetInfo' d:\sample\sample\Sample.c(4) : error C2059: 構文エラー : ';' d:\sample\sample\Sample.c(4) : error C2059: 構文エラー : ')' ビルドログは "file://d:\Sample\Sample\Debug\BuildLog.htm" に保存されました。 Sample - エラー 3、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== ■Sample.c #include "stdafx.h" Info GetInfo(){ return 0; } int main(){ return 0; } ■stdafx.h #pragma once #include "def.h" #include <stdio.h> #include <tchar.h> Info GetInfo(); ■def.h typedef struct Info{ int a; int b; int c; } Info;

  • DLL関数を使ったプログラム

     DLL関数を使ったプログラムを動かしたんですが、ERRORが解決できず 困っています。DLLを作成したのはいいのですが、それをLoadLibraryで読み込もうとしても指定したプロシージャが見つからないというエラーになるようです。使用している環境はVisual Studio.NET2003です。  以下はDLLのソースです。 // plug.c // #include <windows.h> #include <stdio.h> __declspec(dllexport) void CALLBACK TestFunc() {    printf("DLLのTestFunc()関数が実行されました。\n"); } これをビルドするとplug.dllとplug.expとplug.libが作成されました。  そしてこれを使用したプログラムが // stab.c // #include <windows.h> #include <stdio.h> typedef void (*TestFunc)(void); void main() {     HMODULE hModule;     DWORD error;     TestFunc funcPointer;     hModule = LoadLibrary(TEXT("plug"));     error = GetLastError();//error値が127     funcPointer = (TestFunc)GetProcAddress(hModule,TEXT("TestFunc"));     funcPointer();     FreeLibrary(hModule);     getchar(); } LoadLibrary関数を使用してアプリのメモリ空間にDLLを読み込もうとしているんですが、ここでハンドルが正確に渡されていないみたいなんです。どうしてこうなるのか分かりません。わかる方いらっしゃったらよろしくお願いします。

  • 基本クラスに派生クラスのインスタンスを持たせたいのですが.....

    A.h//////// #pragma once #include "B.h" class A{ B* b; } B.h/////// #pragma once #include "A.h" class B : public A{ } ////////////// 上のようなクラス構成にさせたいのですが..... #include "A.h"をB.hに追加したところでエラーが出ます。 基本クラスに派生クラスのインスタンスを持たせたいのですが.... どのようにすれば良いでしょうか? エラー内容は : error C2143: 構文エラー : ';' が '*' の前にありません。 : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません : error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません この三つが出ます。 何方かよろしくお願いしますm(_ _)m

  • このプログラムを見てください(C言語) m( _ _ )m

    現在乱数を使ったプログラムを作っています。 下のプログラムでコンパイルではエラーがでませんが、実行するとデバッグエラーが出てきます。コンパイラにはbccを使っています。恐らく原因は別の関数でbに値を代入してそれをaに代入しているからだろうと思いますが、なぜこれがいけないのかが分かりません。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> int ran, a=1, b, c; void test(void){ b=8; } void main(){ srand(time(NULL)); a=b;//ここを無くすとなぜかエラーが出ない。 while(1){ ran=rand()%(a*2)+1; switch(ran){ case 1: c=1; break; case 2: c=1; break; case 3: c=1; break; case 4: c=2; break; case 5: c=2; break; case 6: c=3; break; case 7: c=3; break; case 8: c=4; break; } printf("%d",c);printf("何か押してください\n");getch(); } }

  • 【VS2008 C++】2つのプロジェクト間で共通の関数を使いたい

    【VS2008 C++】2つのプロジェクト間で共通の関数を使いたい WindowsXP上で visual studio 2008 C++ express editionを 使用しています。 1つのソリューションに2つのプロジェクトをつくり、 その2つに共通の関数を使用させたいのですが、どのように 設定すればよいか教えて頂けませんでしょうか。 ソースの内容は以下のとおりです。 具体的には、mainB.cppでcommon.cppの関数を 呼び出したいです。 //common.cpp #include <stdio.h> void showCommon(){ printf("---common-----\n"); } //common.h #include<stdio.h> void showCommon(); //mainA.cpp #include<stdio.h> #include "common.h" void main(){ printf("---mainA-----\n"); showCommon(); } //mainB.cpp #include<stdio.h> #include "common.h" void main(){ printf("---mainB-----\n"); showCommon(); }

  • PIC18F2550・コンパイルできない(再掲)

    初めて投稿します。 技術職(機械系)の会社員です。 マイコンプログラム作成歴:約3ヶ月のほぼド素人です。 現在、会社の技術研修でPIC18F2550を使ったライントレーサの動作プログラムを作成しています。先日までPIC16F84A&88でのプログラミングを行なっており、基本は理解できているつもりです。 …が、これまで見た事のないエラーコードが出てしまい、理由がわからず困っています。 エラーコードは、[1101]lvalue required と[1105]symbol '○○○' has not been defined というもので、コンパイラのユーザーガイドを見ると、変数(GIE,LATA0等)の認識ができない?エラーのようです。ヘッダーファイルのインクルードもしており、これまでの84A&88では出なかったエラーです。 webも調べましたが、わかりませんでした。 作成環境はMPLAB V8.36、MPLAB C18コンパイラV3.33 です。 エラーメッセージ画面添付、ソースコード掲載しますので、PICプログラムに精通されている方、間違い部分をご教授頂けないでしょうか? 何卒ご協力のほどよろしくお願いします。 --【以下、コード抜粋】-- //●使用マイコン:PIC18F2550 //===《初期設定》=== //---<ヘッダーファイル>--- #include<p18f2550.h> #include"delays.h" //---<コンフィグレーション>--- #pragma config PLLDIV = 5 #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 #pragma config FOSC = HSPLL_HS #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config PWRT = ON #pragma config BOR = OFF #pragma config BORV = 3 #pragma config VREGEN = OFF #pragma config WDT = OFF #pragma config WDTPS = 1 #pragma config MCLRE = ON #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = ON #pragma config STVREN = OFF #pragma config LVP = OFF #pragma config XINST = OFF #pragma config DEBUG = OFF #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF #pragma config CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF #pragma config EBTRB = OFF //---<関数宣言>--- void ioport(void); void interr(void); void pwm_settei(void); void move_A(void); void move_B(void); void delay_ms(long); //---<変数宣言>--- int c_flg = 0; //変数「c_flg」を宣言 //------------------------------------------------------------ //===《動作プログラム》=== //---<メイン関数>--- void main() { ioport(); interr(); pwm_settei(); while(1) { move_A(); } } //---<サブルーチン>--- void ioport(void) //[入出力ポート初期設定] { ADCON1 = 0b00001111; //A/D設定:全ポートデジタル TRISA = 0b00000000; //ポートA・I/O設定 TRISB = 0b11111111; //ポートB・I/O設定 TRISC = 0b00110000; //ポートC・I/O設定 } void interr(void) //[割り込み初期設定] { GIE = 1; //グローバル割り込み設定:許可 TMR2IE = 1; //タイマ2割り込み設定:許可 } --【途中省略】-- void move_A(void) //[動作A(直線&曲線走行モード)] { switch(PORTB) { case 0b01000000 : //センサB(内左)認識 CCPR1L = 100; //CCP1 Duty値設定 CCPR2L = 30; //CCP2 Duty値設定 LATC7 = 1; //モータR1:正転 LATA0 = 1; //モータL1:正転 LATC6 = 1; //モータR2:ON LATA1 = 1; //モータL2:ON break; --【以下続く】--