WinapiとCdecl

概要

WinapiとCdecl

dllの場合、C++側のExport関数は通常「WINAPI」を呼び出し規約として付けますが、
まれに何も付けないことも考えられます。
何も付けない場合(コンパイル時のオプションにもよりますが)、基本はcdeclを付けたことと同じこととなります。

例えば、秀丸の場合、本体のHidemaru.exeのExport関数は、全てWINAPIとなっていますが、
HmOutputPane.dllやHmExplorerPane.dllのExport関数は、全てcdeclとなっています。

このため、C#から呼ぶ際にはどちらなのかを明示する必要があります。

WinapiとCdecl

C++側がWINAPIなら「CallingConvention = CallingConvention.Winapi」
cdeclなら「CallingConvention = CallingConvention.Cdecl」

を付ければよいでしょう。
それ以外と使うことはほぼないと思われます。

  • C++側のソース

    Dll1.dllとしてコンパイル
    #include <windows.h>
    #include <cstddef>
    #include <iostream>
    
    using namespace std;
    
    
    // BYTE受け取り (WINAPI)
    extern "C" void __declspec(dllexport) WINAPI dllbyte_of_winapi(const BYTE a) {
        cout << a << "," << (int)a << endl;
    }
    
    // Char受け取り (WINAPI)
    extern "C" void __declspec(dllexport) WINAPI dllchar_of_winapi(const char b) {
        cout << b << endl;
    }
    
    // BYTE受け取り (cdecl)
    extern "C" void __declspec(dllexport) cdecl dllbyte_of_cdecl(const BYTE a) {
        cout << a << "," << (int)a << endl;
    }
    
    // Char受け取り (cdecl)
    extern "C" void __declspec(dllexport) cdecl dllchar_of_cdecl(const char b) {
        cout << b << endl;
    }
    
  • C#側のソース

    test1.cs
    using System;
    using System.Runtime.InteropServices;
    
    namespace test1
    {
        internal class Program
        {
            [DllImport("Dll1.dll", CallingConvention = CallingConvention.Winapi)]
            static extern void dllbyte_of_winapi(byte a);
    
            [DllImport("Dll1.dll", CallingConvention = CallingConvention.Winapi)]
            static extern void dllchar_of_winapi(char b);
    
            [DllImport("Dll1.dll", CallingConvention = CallingConvention.Cdecl)]
            static extern void dllbyte_of_cdecl(byte b);
    
            [DllImport("Dll1.dll", CallingConvention = CallingConvention.Cdecl)]
            static extern void dllchar_of_cdecl(char b);
    
    
            static void Main(string[] args)
            {
                byte a = 0x41;
    
                dllbyte_of_winapi(a);
                dllbyte_of_cdecl(a);
    
                char b = 'b';
    
                dllchar_of_winapi(b);
                dllchar_of_cdecl(b);
    
                Console.ReadKey();
            }
        }
    }