WinAPI/COMインタフェースの使用時の呼び出し規則
39789 ワード
背景:ネットで調べたところ、C#の呼び出し約束はstdcallだった.
前提:ここでのテストは主にC#プロジェクトの「ターゲットプラットフォーム」が「x 86」の場合、その他は具体的なテストがありません...
テスト環境:Win 7 64ビット、vs 2013はexe(C#、現在使用している.netバージョンは3.5)、VC 6はdllを作成します.
ZC:指定したC#一般関数呼び出し規則を表示する方法は調べられませんでした.しかし、私がデバッグしたとき、stdcallではありませんでした.
ZC:具体的には、ecxはthisポインタを格納し、edxは最初のパラメータを格納し、残りのパラメータは左から右に順にpushします.この呼び出しルールの名前は調べられませんでした...
ZC:C#でWinAPI/COMインタフェース関数を呼び出す場合、一見上の呼び出しルールでもありますが、さらに下位のcallについていくとパラメータを再編成してstdcallでWinAPI/COMインタフェース関数を呼び出すことがわかります.
1、exe(C#.netバージョンは3.5)
1.1、ComIntf.cs(インタフェース定義コードファイル)
1.2、インタフェースのテストコード:
2、VC6 -- DLL
2.1、DLL_Z.cpp
2.2、
2.3、Z.def
3、
3.1、C#exe呼び出し普通のDLL導出関数
(1)、DLL導出関数TestZZ()に対して、指定呼び出し規則がstdcallであることを表示する、(2)、指定呼び出し規則を表示しない、
DLLのデバッグ追跡により、C#独自の呼び出し規則の下でstdcallを構築してTestZZを呼び出すことがわかります(...)
ZC:なぜDLLでアセンブリをデバッグするのですか.►C#でアセンブリを見てみると、C#の関数callしか見えず、DLLの関数callには入れません.F 11(文ごと)を押して更なる関数callに入ることができなくて、現れる効果はF 10(過程ごと)のようです
3.2、C#exe呼び出しDLLエクスポートのCOM型interface
C#独自の呼び出し規則の下でも、インタフェース関数を呼び出すためにstdcallを構築しているようです(C#のinterface宣言にはどの呼び出し規則を使用するか指定されていませんが)
4、
また疑問があれば、デバッグしてみましょう.VS 2013デバッグアセンブリ、VC 6 DLLデバッグアセンブリ、全部見てみましょう.
5、
転載先:https://www.cnblogs.com/csskill/p/5390818.html
前提:ここでのテストは主にC#プロジェクトの「ターゲットプラットフォーム」が「x 86」の場合、その他は具体的なテストがありません...
テスト環境:Win 7 64ビット、vs 2013はexe(C#、現在使用している.netバージョンは3.5)、VC 6はdllを作成します.
ZC:指定したC#一般関数呼び出し規則を表示する方法は調べられませんでした.しかし、私がデバッグしたとき、stdcallではありませんでした.
ZC:具体的には、ecxはthisポインタを格納し、edxは最初のパラメータを格納し、残りのパラメータは左から右に順にpushします.この呼び出しルールの名前は調べられませんでした...
ZC:C#でWinAPI/COMインタフェース関数を呼び出す場合、一見上の呼び出しルールでもありますが、さらに下位のcallについていくとパラメータを再編成してstdcallでWinAPI/COMインタフェース関数を呼び出すことがわかります.
1、exe(C#.netバージョンは3.5)
1.1、ComIntf.cs(インタフェース定義コードファイル)
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Runtime.InteropServices;
5 using System.Text;
6
7 namespace WindowsFormsApplication
8 {
9 [Guid("FCE9DCF3-9E38-441C-B10F-2BA31B57DCDC")]
10 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
11 public interface IntfTest
12 {
13 unsafe Int32 TestZ01(int _i, int _j, int _k, int* _piOut);
14 unsafe Int32 TestZ02(int _i, int _j, int _k, int _m, int* _piOut);
15 unsafe Int32 TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut);
16 }
17 }
1.2、インタフェースのテストコード:
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.Data;
6 using System.Drawing;
7 using System.Runtime.InteropServices;
8 //using System.Linq;
9 using System.Text;
10 //using System.Threading.Tasks;
11 using System.Windows.Forms;
12
13 namespace WindowsFormsApplication
14 {
15 public partial class Form1 : Form
16 {
17 public Form1()
18 {
19 InitializeComponent();
20 }
21
22 private void button1_Click(object sender, EventArgs e)
23 {
24 //*
25 TdrSvgDll svgdll = new TdrSvgDll();
26 AAA(1, 2, 3); // C#
27 int kk = TestZZ(1, 2, 3, 4 ,5); // DLL
28
29 TestCB(callback);
30 MessageBox.Show(Fhh.ToString());
31
32 TRect rect = new TRect();
33 MessageBox.Show(Marshal.SizeOf(rect).ToString());
34
35 ArrayList list = new ArrayList();
36 //list.[i];
37 //*/
38 }
39
40 int AAA(int i, int j, int k)
41 {
42 return (i + j + k);
43 }
44
45 //[DllImport("DLL_Z.dll", EntryPoint="TestZZ", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
46 [DllImport("DLL_Z.dll", EntryPoint = "TestZZ", CharSet = CharSet.Auto)]
47 public static extern int TestZZ(Int32 i, Int32 j, Int32 k, Int32 m, Int32 n);
48
49 [DllImport("DLL_Z.dll", EntryPoint = "TestCB", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
50 public static extern void TestCB([MarshalAs(UnmanagedType.FunctionPtr)] Callback_Test01 _callback);
51
52 //
53 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
54 public delegate int Callback_Test01(int _i, int _j, int _k, int _m, int _n);
55
56 public static int Fhh = 0;
57 //
58 Callback_Test01 callback =
59 (i, j, k, m, n) =>
60 {
61 Fhh = (i + j + k + m + n); //
62 //return (i + j + k + m + n);
63 return Fhh;
64 };
65
66 private void button2_Click(object sender, EventArgs e)
67 {
68 // / DLL
69 IntfTest intfTest = null;
70 int iRtn = IntfTest_Get(ref intfTest);
71
72 unsafe
73 {
74 int iOut = 0;
75 intfTest.TestZ01(1, 2, 3, &iOut);
76 }
77 }
78
79 [DllImport("DLL_Z.dll", EntryPoint = "IntfTest_Get", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
80 public static extern int IntfTest_Get(ref IntfTest _intfTest);
81 }
82 }
2、VC6 -- DLL
2.1、DLL_Z.cpp
1 // DLL_Z.cpp : Defines the entry point for the DLL application.
2 //
3
4 #include "stdafx.h"
5 #include "zz.h"
6
7 BOOL APIENTRY DllMain( HANDLE hModule,
8 DWORD ul_reason_for_call,
9 LPVOID lpReserved)
10 {
11 return TRUE;
12 }
13
14 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
15 //
16
17 extern "C" __declspec(dllexport) int __stdcall TestZZ(int i, int j, int k, int m, int n)
18 {
19 return (i+j+k+m+n);
20 }
21
22 extern "C" __declspec(dllexport) void TestCC(int i, int j)
23 {
24 }
25
26 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
27 // exe ,
28
29 typedef int (__stdcall * Callback_Test01)(int, int, int, int, int);
30
31 extern "C" __declspec(dllexport) void __stdcall TestCB(Callback_Test01 _callback)
32 {
33 if (_callback)
34 {
35 int i = _callback(1,2,3,4,5);
36 }
37 }
38
39 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
40 // interface, exe
41
42 IntfTest *g_pIntfTest;
43
44 extern "C" __declspec(dllexport) int IntfTest_Get(IntfTest **_ppIntfTest)
45 {
46 (*_ppIntfTest) = NULL;
47
48 if ( NULL != g_pIntfTest )
49 {
50 // "IntfTest*" ,C# , -1,∴ +1
51 // "IntfTest*" , ,∴ +1
52 g_pIntfTest->AddRef();
53 (*_ppIntfTest) = g_pIntfTest;
54 return 0;
55 }
56
57 // ***
58 IntfTest *pObj = new TintfTest();
59
60 IUnknown *pIUnknown = NULL;
61 HRESULT hr = pObj->QueryInterface(IID_IUnknown, (void**)&pIUnknown);
62 pObj->Release();
63 pObj = NULL;
64
65 if (FAILED(hr))
66 {
67 return -1;
68 }
69 else
70 {
71 hr = pIUnknown->QueryInterface(IID_IntfTest, (void**)&g_pIntfTest);
72 pIUnknown->Release();
73 pIUnknown = NULL;
74
75 if (SUCCEEDED(hr))
76 {
77 (*_ppIntfTest) = g_pIntfTest;
78 }
79 else
80 {
81 return -2;
82 }
83 }
84 return 0;
85 }
2.2、
1 #ifndef __zzz_2016__
2 #define __zzz_2016__
3
4 #include
5
6 // // {FCE9DCF3-9E38-441C-B10F-2BA31B57DCDC}
7 static const IID IID_IntfTest =
8 { 0xfce9dcf3, 0x9e38, 0x441c, { 0xb1, 0xf, 0x2b, 0xa3, 0x1b, 0x57, 0xdc, 0xdc } };
9
10
11 interface IntfTest : public IUnknown
12 {
13 virtual HRESULT __stdcall TestZ01(int _i, int _j, int _k, int* _piOut) = 0;
14 virtual HRESULT __stdcall TestZ02(int _i, int _j, int _k, int _m, int* _piOut) = 0;
15 virtual HRESULT __stdcall TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut) = 0;
16 };
17
18 class TintfTest :public IntfTest
19 {
20 public:
21 TintfTest();
22
23 public:
24 virtual HRESULT __stdcall TestZ01(int _i, int _j, int _k, int* _piOut);
25 virtual HRESULT __stdcall TestZ02(int _i, int _j, int _k, int _m, int* _piOut);
26 virtual HRESULT __stdcall TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut);
27
28 private:
29 long FlCount;
30 public:
31 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppv)
32 {
33 if (iid == IID_IUnknown)
34 {
35 *ppv = static_cast(this);
36 }
37 else if (iid == IID_IntfTest)
38 {
39 *ppv = static_cast(this);
40 }
41 else
42 {
43 *ppv = NULL;
44 return E_NOINTERFACE;
45 }
46
47 AddRef();
48
49 return S_OK;
50 }
51
52 virtual ULONG STDMETHODCALLTYPE AddRef()
53 {
54 return ++FlCount;
55
56 //return InterlockedIncrement(&FlCount);
57 }
58
59 virtual ULONG STDMETHODCALLTYPE Release()
60 {
61 if (--FlCount == 0)
62 {
63 delete this;
64 return 0;
65 }
66 return FlCount;
67
68 //if (InterlockedDecrement(&FlCount) == 0)
69 //{
70 // delete this;
71 // return 0;
72 //}
73 //return FlCount;
74 }
75 };
76
77 TintfTest::TintfTest():
78 FlCount(0)
79 {
80 this->AddRef();
81 }
82
83 HRESULT __stdcall TintfTest::TestZ01(int _i, int _j, int _k, int* _piOut)
84 {
85 *_piOut = (_i + _j + _k);
86 return S_OK;
87 }
88
89 HRESULT __stdcall TintfTest::TestZ02(int _i, int _j, int _k, int _m, int* _piOut)
90 {
91 return S_OK;
92 }
93
94 HRESULT __stdcall TintfTest::TestZ03(int _i, int _j, int _k, int _m, int _n, int* _piOut)
95 {
96 return S_OK;
97 }
98
99
100 #endif // __zzz_2016__
2.3、Z.def
1 LIBRARY DLL_Z
2 EXPORTS
3 TestZZ
4 TestCC
5 TestCB
6 IntfTest_Get
3、
3.1、C#exe呼び出し普通のDLL導出関数
(1)、DLL導出関数TestZZ()に対して、指定呼び出し規則がstdcallであることを表示する、(2)、指定呼び出し規則を表示しない、
DLLのデバッグ追跡により、C#独自の呼び出し規則の下でstdcallを構築してTestZZを呼び出すことがわかります(...)
ZC:なぜDLLでアセンブリをデバッグするのですか.►C#でアセンブリを見てみると、C#の関数callしか見えず、DLLの関数callには入れません.F 11(文ごと)を押して更なる関数callに入ることができなくて、現れる効果はF 10(過程ごと)のようです
3.2、C#exe呼び出しDLLエクスポートのCOM型interface
C#独自の呼び出し規則の下でも、インタフェース関数を呼び出すためにstdcallを構築しているようです(C#のinterface宣言にはどの呼び出し規則を使用するか指定されていませんが)
4、
また疑問があれば、デバッグしてみましょう.VS 2013デバッグアセンブリ、VC 6 DLLデバッグアセンブリ、全部見てみましょう.
5、
転載先:https://www.cnblogs.com/csskill/p/5390818.html