export関数の呼び出し方の型の判定

概要

秀丸マクロからloaddllされたdllの関数を呼び出す方式は、

  • dllfunc
  • dllfuncw
  • dllfuncstr
  • dllfuncstrw

と4つあります。

このうち、dllfuncとdllfuncstrは、マルチバイト形式であり、Unicodeの範囲には対応できませんので、現在ではほとんど意味を持ちません。
Hm.CppInvokeでも、対象としているのは原則「dllfuncw」と「dllfuncstrw」の2つだけです。

関数呼び出しや返り値の型チェックの例

C++側のソース

dllmain.cpp
#include "HmCppInvoke.h"
#include <thread>
#include <algorithm>
using namespace Hidemaru;
using namespace std;

extern "C" __declspec(dllexport) THmNumber test(THmNumber arg1, wchar_t *arg2) {

    Hm.funcDllExport();
 
    // 取り出すなら必ず、Hm.funcDllExport() の直後に呼び出すこと。
    // マクロから呼び出された引数の型リストを得る
    auto argtype_list = Hm.DllFuncCalledType.getFuncParamTypeList();

    // 取り出すなら必ず、Hm.funcDllExport() の直後に呼び出すこと。
    // 秀丸マクロが要求している関数の返り値の型を得る
    auto rettype = Hm.DllFuncCalledType.getFuncReturnType();

    // 秀丸マクロの方からwchar_t渡しではなく、char_t渡ししているパラメータがある。(文字列引数があるのに、dllfuncwではなく、dllfuncで呼び出している)
    bool list_has_char_type = std::any_of(argtype_list.begin(), argtype_list.end(), [](auto x) { return x == decltype(Hm.DllFuncCalledType)::DLLFUNCPARAM::CHAR_PTR; } );
    if (list_has_char_type) {
        MessageBox(NULL, L"ワイド文字ではなく、マルチバイト文字で関数を呼び出しています。w付きのワイド文字渡しとなるdllfuncw関数を利用してください。", L"関数呼び出しミス", NULL);
        return 0;
    }

    // 数値を返す関数なのに、マクロの呼び出しが、数値を返す前提になっていない。(dllfuncstrwなど誤った呼び出し)
    if (rettype == decltype(Hm.DllFuncCalledType)::DLLFUNCRETURN::INT || rettype == decltype(Hm.DllFuncCalledType)::DLLFUNCRETURN::DOUBLE) {
        ; // OK
    }
    else if (rettype == decltype(Hm.DllFuncCalledType)::DLLFUNCRETURN::CHAR_PTR) {
        MessageBox(NULL, L"dllfuncstrは呼び出しが間違っています。#r = dllfunw(...) で呼び出してください。", L"関数呼び出しミス", NULL);
        return 0;
    }
    else if (rettype == decltype(Hm.DllFuncCalledType)::DLLFUNCRETURN::WCHAR_PTR) {
        MessageBox(NULL, L"dllfuncstrwは呼び出しが間違っています。#r = dllfunw(...) で呼び出してください。", L"関数呼び出しミス", NULL);
        return 0;
    }

    // こういった本格的にHm.*** 関数を使うより、上の行で、必ず getFuncParamTypeList()やgetFuncReturnType()を取り出しを終了すること。
    // 後に取得したのでは(裏処理で別関数が呼び出されている都合上)誤った値が返ってくる事がある。
    Hm.OutputPane.output(L"型判定\r\n");

    return 1;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    return TRUE;
}

秀丸マクロ側のソース

dllfuncwの「w」を削除したみたり、あるいは、「$r = dllfuncstrw(#dll, "test", -33, "333");」などと文字列を返す形を要求してみたりしてください。
呼び出し方が違うということでエラーを出すことができることでしょう。

test.mac
#dll = loaddll(currentmacrodirectory + @"\dll1.dll");
#r = dllfuncw(#dll, "test", -33, "333");
message($r);
freedll(#dll);