14

私はC++dllインポートトピックの初心者で、質問は非常に簡単かもしれませんが、Googleで見つけることができません。

私は非常に単純なC++win32 dllを持っています:

#include <iostream>

using namespace std;

extern "C"
{
    __declspec(dllexport) void __stdcall DisplayHellowFromDLL()
    {
        cout<<"Hi"<<endl;
    }
}

このメソッドをC#から呼び出すと、問題はありません。ここにC#コードがあります。

namespace UnmanagedTester
{
    class Program
    {
        [DllImport(@"C:\CGlobalDll")]
        public static extern void DisplayHellowFromDLL();

        static void Main(string[] args)
            {
                Console.WriteLine("This is C# program");
                DisplayHellowFromDLL();
            }
        }
    }

予想どおり、出力は「これはC#プログラムです」「こんにちは」です。

ここで、C関数の宣言を次のように変更するとします。

__declspec(dllexport) void DisplayHellowFromDLL()

__stdcallがなければ、私も問題はありません。問題は次のとおりです。

__declspec(dllexport)TYPE __stdcallが本当に必要なのはいつですか?また、__ declspec(dllexport)TYPEのみを使用できるのはいつですか?

どうもありがとう。

4

4 に答える 4

17

あなたはそれをこのように考えることができます:

  1. __declspec(dllexport)DLLがエクスポートするパブリック関数として関数を宣言します。

  2. __stdcallその関数によって採用された「呼び出し規約」を参照するかなり低レベルの詳細です。具体的に__stdcallは、呼び出し先がスタックをクリーンアップすることを意味します。

  3. __stdcallisの代わりに__cdecl、これは次のことを意味します。呼び出し元がスタックをクリーンアップします。

__cdecl「自然な」C呼び出し規約です。vararg関数(printfなど)の定義をサポートします。

__stdcallはDLL関数のデフォルトの呼び出し規約であるため、DLL APIを介してのみこれらの関数を呼び出す場合は、これを指定する必要はありません。

これはあなたが観察していることを説明するはずです。

于 2011-06-13T18:22:29.247 に答える
6

関数は引数を取らないため、偶然に機能します。引数を取る関数でこれを行うとすぐに運が不足し始めます。この呼び出しにより、スタックのバランスが崩れ、非常に不健康になります。デバッグすると、pInvokeStackImbalanceMDA警告が表示されます。不均衡なスタックは、しばらくの間見過ごされる可能性があり、リリースビルドでプログラムをクラッシュさせる傾向があります。

于 2011-06-13T18:23:48.130 に答える
3

呼び出し規約を他の規則でコンパイルする場合は、呼び出し規約を指定する必要があります。それ以外の場合は、デフォルトで機能します。

于 2011-06-13T18:07:11.923 に答える
1

Ilya、[プロジェクトのプロパティ]->[構成のプロパティ]->[C / C++]->[詳細設定]->[呼び出し規約]でデフォルトの呼び出し規約を設定することもできます。プロジェクトのデフォルトの呼び出し規約がすでに__stdcall(/ Gz)に設定されている場合は、__stdを追加します

于 2014-05-15T16:36:01.950 に答える