3

私はいくつかのモジュールを含む大規模な C++ プロジェクトを持っています - それらはすべて動的ライブラリにコンパイルされています。Windows、Linux、MacOSX など、複数のプラットフォームをターゲットにしています。

プロファイリング テストにより、いくつかの重要なポイントが明らかになりました。たとえば、ハッシュ コンピューティング、いくつかのベクトル操作など、パフォーマンスが大幅に向上しました。この機能を SSE/MMX を使用してアセンブリに実装しました。

インライン アセンブリが許可されていない Visual C++ の x64 ターゲットに戻すまでは、すべて問題ありませんでした。そして、私は立ち往生しています。また、これらの関数は他のモジュールでも使用されます。

基本的に、私が達成しようとしているのは、アセンブリの DLL 内にあるいくつかの関数を実装することです。私はこれを試しました:

Api.h

extern "C" void DLL_API __stdcall sample_fun(/*args*/);

Api.asm

sample_fun PROC public ;args
.....
sample_fun ENDP

名前マングリングのため、これは明らかに機能しません。

私もこれを試しました:

Api.h

void DLL_API sample_fun(/*args*/);

API.cpp

extern "C" __stdcall sample_fun_impl(/*args*/).

void DLL_API sample_fun(/*args*/)
{
  return sample_fun_impl(/*args*/);
}

Api.asm

sample_fun_impl PROC public ;args
.....
sample_fun_impl ENDP

この場合、まだ解決されていない外部シンボル (sample_fun_impl) に関するリンカ エラーが発生しますが、これは奇妙です。なぜなら、これは実際にはプライベート関数であり、DLL 内からのみ呼び出されるからです。

私がやろうとしていることをすることは可能ですか?

4

1 に答える 1

1

それで、問題は解決しました。これは、いくつかの説明とともに私が望んでいたことの最小限の例です。

Asx.h

namespace Asx
{
#if ASX_PLATFORM_IS64BIT //This is resolved using 'ifdef _M_X64'
    extern ASX_DLL_API ULONGLONG roundup_pow2_64(ULONGLONG value);
#else
    extern ASX_DLL_API DWORD roundup_pow2_32(DWORD value);
#endif
}

Asx.cpp

#include "Asx.h"

#if ASX_PLATFORM_IS64BIT
extern "C" ULONGLONG __cdecl roundup_pow2_64_impl(ULONGLONG value);
#else
extern "C" DWORD __cdecl roundup_pow2_32_impl(DWORD value);
#endif

namespace Asx
{

#if ASX_PLATFORM_IS64BIT
    ULONGLONG roundup_pow2_64(ULONGLONG value)
    {
        return roundup_pow2_64_impl(value);
    }
#else
    DWORD roundup_pow2_32(DWORD value)
    {
        return roundup_pow2_32_impl(value);
    }
#endif

}

Asx_asm_impl.asm

IFNDEF ASX_PLATFORM_IS64BIT
.686P
.MODEL FLAT, C
.XMM
ENDIF

.CODE

IFDEF ASX_PLATFORM_IS64BIT

roundup_pow2_64_impl PROC public, value:QWORD
//Implementation
roundup_pow2_64_impl ENDP

ELSE

roundup_pow2_32_impl PROC public, value:DWORD
//Implementation
roundup_pow2_32_impl ENDP

ENDIF

END

何が問題だったのですか?

1) x64 では呼び出し規約の扱いが異なることを考慮に入れていませんでしたが、偶然にもこれにより問題が発生することはありませんでした。

2) ある時点で、マークされた関数は__cdecl、名前の先頭にアンダースコアを付けてリンカーによって検索されることに気付きました。私dumpbinは問題のある DLL を作成しましたが、それはそこにありましたが、実際には先頭にアンダースコアがありました! roundup_pow2_32_implそこで、宣言をそのままにして、名前を からに変更_roundup_pow2_32_implすると同時に、 を追加しましMODEL FLAT, Cた。

3) ファイル内で IFDEF/IFNDEF を使用しまし.asmた。しかし、目に見えるすべての定義は/clにも見えると仮定しました。違う。必要な定数を手動で追加した後にのみ、すべてが機能し始めました (ファイル プロパティ -> Microsoft マクロ アセンブラー -> 一般 -> プリプロセッサ定義)。mlml64.asm

さまざまな解決策を試してみた結果、すべてが 1 つの大きな混乱に変わったと思います。クリーンセットアップは完璧に機能しました:

メイン.cpp

#include "../Asx/Header.h"

int main(int argc, char** argv)
{
#if ASX_PLATFORM_IS64BIT
    ULONGLONG v = Asx::roundup_pow2_64(4000);
#else
    DWORD v = Asx::roundup_pow2_32(4000);
#endif

    return 0;
}

結果は Win32 と x64: の両方になります4096

ボグダンに感謝!x64 での規則指定子の呼び出しに関する彼のヒントがなければ、私はこれを解決できません。

于 2015-03-25T23:42:16.900 に答える