0

もともとMSVSで書かれたライブラリ(dll)があり、クロスプラットフォーム(Mac / Win)を作成する必要があります。XCodeを使い始めましたが、新しいEmbarcadero C ++ビルダーXE3を使用すると、1つの開発環境がより良い方法になると考えています。ホストアプリケーションはDelphiで記述されているため、1セットのツールに移動する理由があります。

私の既存のコードでは、すべてがcdeclですが、これをC++ビルダーで動作させることはできません。stdcallに変換すると正常に動作しますが、OSXでライブラリを使用する場合は、cdeclを使用する必要があります。

MSVCでは、次のように関数をエクスポートします。

extern "C" __declspec(dllexport) int Init(char * init_dir, DebugCallbackFunc f, DeviceCallbackFunc f1)

C ++ Builderでは、次のようにエクスポートしています。

extern "C" __declspec( dllexport ) int _cdecl Init(char * init_dir, DebugCallbackFunc f, DeviceCallbackFunc f1)

問題は、cdeclを使用するとDelphiホストアプリケーションがGetProcAddressで常にNULLを返すが、stdcallに変更すると正常に動作することです。

TUDMXInit = function(p: PAnsiChar; f: TDebugCallbackFunc; f1: TDeviceCallbackFunc): integer; cdecl;

また、OSXでエクスポートされた関数のプレフィックスとなる「_」を処理するための最良の方法の例をいただければ幸いです。すべての関数の前にこれを追加するために条件を使用する必要がありますか?

前もって感謝します。マーティン

4

2 に答える 2

4

これを行う通常の方法は、マクロを使用することです。declspec と cdecl/stdcall は Windows 固有です。あなたが望むOSX(および他のUnix)での呼び出しは

extern "C" int Init(char * init_dir, DebugCallbackFunc f, DeviceCallbackFunc f1)

したがって、通常の方法はマクロを定義することです例: DLL_EXPORT

Windows ライブラリのビルドで WINDOWS が定義されていると仮定します。

#ifdef WINDOWS
  #define DLLEXPORT  __declspec( dllexport )
#else
  #define DLLEXPORT
#endif

また、ここのように DLL をビルドするとき、または必要なときに DLL を呼び出すときに、この定義を正しく動作させることができます。__declspec( dllimport )

于 2012-10-09T10:28:16.493 に答える
2

このような違いを処理する方法は、常に同じ基本的な考え方です: 各コンパイラがそれを行う方法を見て、面倒すぎずに必要なすべてのフォームを生成できるマクロまたはマクロのセットを考え出します。

_cdecl の場合、"EXPORT_CDECL" のような単純なマクロで十分なようです。次に、コンパイラの必要に応じて、これを何も展開しない、「_cdecl」、または「stdcall」に設定できます。

このようなものを使用して、名前に何かを追加することもできます。#define EXPORT_NAME(Name) _##Name

もちろん、個々のコンポーネント (戻り値の型、関数名、関数パラメーター) を取り、結果行全体を吐き出す「大きな」マクロを作成することもできます。

于 2012-10-09T10:26:16.363 に答える