私のコードで明示的にmainCRTStartup関数で通常呼び出される関数を呼び出す方法はありますか?私は特に興味がありますinittermとinitterm_e関数です。私のプログラムがcrtとリンクしているとは思っていましたが、私はinittermを呼び出すことができませんでした。宣言して呼び出しようとしましたが、未定義の参照がありました。明示的にCRTの起動関数を呼び出す方法
これを行う方法はありますか?
私のコードで明示的にmainCRTStartup関数で通常呼び出される関数を呼び出す方法はありますか?私は特に興味がありますinittermとinitterm_e関数です。私のプログラムがcrtとリンクしているとは思っていましたが、私はinittermを呼び出すことができませんでした。宣言して呼び出しようとしましたが、未定義の参照がありました。明示的にCRTの起動関数を呼び出す方法
これを行う方法はありますか?
、および_initterm_e(MSDN _initterm_e
でノートが間違って宣言されている - 実際にそれは_PIFV
タイプを使用)異なるCRT用のDLLでエクスポートされます。それはlibファイルでも宣言されています。この機能の実装は非常に簡単です:
typedef void (__cdecl *_PVFV)();
void _initterm(const _PVFV *ppfn, const _PVFV *end)
{
do
{
if (_PVFV pfn = *++ppfn)
{
pfn();
}
} while (ppfn < end);
}
typedef int (__cdecl *_PIFV)();
int _initterm_e(const _PIFV *ppfn, const _PIFV *end)
{
do
{
if (_PIFV pfn = *++ppfn)
{
if (int err = pfn()) return err;
}
} while (ppfn < end);
return 0;
}
したがって、独自の実装を使用してインポートすることができます。 ここで、より高速な質問 - 入力パラメータとしてどのような使用ですか?
は、C++場所 C++グローバル初期化のための(".CRT$XCA", ".CRT$XCZ")
セクションを使用します(どのように最小
CLコンパイラ)
を言います。 extern "C"
{
#pragma const_seg(".CRT$XCA")
const _PVFV __xc_a = 0;
#pragma const_seg(".CRT$XCZ")
const _PVFV __xc_z = 0;
#pragma const_seg(".CRT$XIA")
const _PVFV __xi_a = 0;
#pragma const_seg(".CRT$XIZ")
const _PVFV __xi_z = 0;
}
/*
* do initializations
*/
initret = _initterm_e(&__xi_a, &__xi_z);
if (initret != 0)
return initret;
/*
* do C++ initializations
*/
_initterm(&__xc_a, &__xc_z);
が、ここでは非常に良い理解必要 - 何を、なぜ私たちは、あなたがそれをリンクすることはできませんので、それが輸出されていない
に感謝します。ちょうど速い明確化:関数ポインタはpreincrementedの代わりにpostincrementedするべきですか? @MarcinK。 –
。 - 私は '__xc_a'をポインタの開始として使います。したがって、beginの 'ppfn'は' 0 'の '__xc_a'とまったく同じです。beginの' * ppfn'は0です。preincrementedは小さな最適化です。しかし、もしポストインクリメントがエラーでないなら – RbMm
をやって:私たちは、次の行うことができます。どちらが良いのですか、これを行うことは良い終わりに来る可能性は低いです。プログラムを再起動するだけです。 –
@ HansPassant - いいえ、このAPIがエクスポートされます。 * msvcrt.dll *と言ってください。 libファイルではこの名前も見つけられます – RbMm
*私のプログラムはcrt *にリンクされています* * lib *を正確に使用していますか?このlibを開き、 'initterm'文字列を検索する必要があります。あなたが間違って宣言したので、それが存在し、libファイルと未定義の参照だと思ってください – RbMm