youtube:vba-dll-005
差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
youtube:vba-dll-005 [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1 | youtube:vba-dll-005 [2024/07/12 02:46] (現在) – freemikan | ||
---|---|---|---|
行 1: | 行 1: | ||
+ | ====== Toymath3 ====== | ||
+ | |||
+ | 作成日: 2023-09-02 (土) | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | そのうち説明を追記予定。 | ||
+ | ===== test_Toymath3.xls ===== | ||
+ | |||
+ | ==== Sheet1 (Sheet1) ==== | ||
+ | |||
+ | <file vba> | ||
+ | Sub test_Toymath3() | ||
+ | ' | ||
+ | 'Dim Calc As ToymathLib3.Calculator | ||
+ | 'Set Calc = CreateObject(" | ||
+ | |||
+ | ' | ||
+ | Dim Calc As New ToymathLib3.Calculator | ||
+ | |||
+ | X = Calc.Add(100, | ||
+ | Debug.Print X | ||
+ | |||
+ | Debug.Assert Calc.Add(10, | ||
+ | Debug.Assert Calc.Sub(10, | ||
+ | Debug.Assert Calc.Mul(10, | ||
+ | Debug.Assert Calc.Div(10, | ||
+ | End Sub | ||
+ | </ | ||
+ | |||
+ | ===== Toymath3 ===== | ||
+ | |||
+ | ==== Makefile ===== | ||
+ | |||
+ | <file makefile> | ||
+ | MODNAME = toymath3 | ||
+ | DLLFILE = ${MODNAME}.dll | ||
+ | IDLSRC = ${MODNAME}.idl | ||
+ | DEFFILE = ${MODNAME}.def | ||
+ | TLBFILE = ${MODNAME}.tlb | ||
+ | IDLOUT = ${MODNAME}.h ${MODNAME}_i.c ${MODNAME}_p.c ${TLBFILE} dlldata.c | ||
+ | RCSRC = ${MODNAME}.rc | ||
+ | RCBIN = ${MODNAME}.res | ||
+ | OUTDIR = output | ||
+ | SRCS = \ | ||
+ | calculator.cpp \ | ||
+ | calculatorclass.cpp \ | ||
+ | modulelock.cpp \ | ||
+ | exports.cpp | ||
+ | OBJS = ${SRCS: | ||
+ | DEPS = ${SRCS: | ||
+ | CPPFLAGS = | ||
+ | CXXFLAGS = -Wall -std=c++20 -fPIC | ||
+ | LDFLAGS = | ||
+ | LDLIBS = -lole32 -loleaut32 -luuid | ||
+ | |||
+ | .PHONY: all | ||
+ | all: ${OUTDIR} ${IDLOUT} ${OUTDIR}/ | ||
+ | |||
+ | ${OUTDIR}/ | ||
+ | ${CXX} -shared -o $@ $^ ${DEFFILE} ${LDFLAGS} ${LDLIBS} | ||
+ | |||
+ | ${OUTDIR}/ | ||
+ | ${CXX} -c ${CXXFLAGS} -o $@ $< -MMD -MP ${CPPFLAGS} | ||
+ | |||
+ | -include ${DEPS} | ||
+ | |||
+ | ${IDLOUT}: ${IDLSRC} | ||
+ | midl $< | ||
+ | | ||
+ | ${OUTDIR}/ | ||
+ | windres $< -O COFF -o $@ | ||
+ | |||
+ | ${OUTDIR}/ | ||
+ | gcc -c -o $@ $< | ||
+ | |||
+ | ${OUTDIR}: | ||
+ | mkdir -p ${OUTDIR} | ||
+ | |||
+ | .PHONY: clean | ||
+ | clean: | ||
+ | ${RM} ${IDLOUT} | ||
+ | ${RM} -R ${OUTDIR} | ||
+ | |||
+ | .PHONY: install | ||
+ | install: all | ||
+ | cp -f ${OUTDIR}\${DLLFILE} C:\code\lib | ||
+ | </ | ||
+ | |||
+ | ==== calculator.h ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef CALCULATOR_H | ||
+ | #define CALCULATOR_H | ||
+ | |||
+ | #include " | ||
+ | |||
+ | class Calculator : public ICalculator { | ||
+ | public: | ||
+ | Calculator(void); | ||
+ | |||
+ | protected: | ||
+ | virtual ~Calculator(void); | ||
+ | |||
+ | public: | ||
+ | STDMETHODIMP QueryInterface(REFIID riid, void **ppv); | ||
+ | STDMETHODIMP_(ULONG) AddRef(void); | ||
+ | STDMETHODIMP_(ULONG) Release(void); | ||
+ | | ||
+ | STDMETHODIMP Add(long x, long y, long *result); | ||
+ | STDMETHODIMP Sub(long x, long y, long *result); | ||
+ | STDMETHODIMP Mul(long x, long y, long *result); | ||
+ | STDMETHODIMP Div(long x, long y, long *result); | ||
+ | | ||
+ | private: | ||
+ | LONG m_cRef; | ||
+ | }; | ||
+ | |||
+ | #endif // CALCULATOR_H | ||
+ | </ | ||
+ | |||
+ | ==== calculator.cpp ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | #include < | ||
+ | |||
+ | extern IID const IID_ICalculator; | ||
+ | |||
+ | Calculator:: | ||
+ | |||
+ | Calculator:: | ||
+ | |||
+ | STDMETHODIMP Calculator:: | ||
+ | if (riid == IID_IUnknown) { | ||
+ | *ppv = static_cast< | ||
+ | } else if (riid == IID_ICalculator) { | ||
+ | *ppv = static_cast< | ||
+ | } else { | ||
+ | *ppv = nullptr; | ||
+ | return E_NOINTERFACE; | ||
+ | } | ||
+ | | ||
+ | reinterpret_cast< | ||
+ | return S_OK; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP_(ULONG) Calculator:: | ||
+ | if (m_cRef == 0) { | ||
+ | LockModule(); | ||
+ | } | ||
+ | return InterlockedIncrement(& | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP_(ULONG) Calculator:: | ||
+ | LONG res = InterlockedDecrement(& | ||
+ | if (res == 0) { | ||
+ | delete this; | ||
+ | UnlockModule(); | ||
+ | } | ||
+ | return res; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP Calculator:: | ||
+ | *result = x + y; | ||
+ | return S_OK; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP Calculator:: | ||
+ | *result = x - y; | ||
+ | return S_OK; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP Calculator:: | ||
+ | *result = x * y; | ||
+ | return S_OK; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP Calculator:: | ||
+ | *result = x / y; | ||
+ | return S_OK; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== calculatorclass.h ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef CALCULATORCLASS_H | ||
+ | #define CALCULATORCLASS_H | ||
+ | |||
+ | #include < | ||
+ | |||
+ | class CalculatorClassObject : public IClassFactory { | ||
+ | public: | ||
+ | CalculatorClassObject(void); | ||
+ | | ||
+ | protected: | ||
+ | virtual ~CalculatorClassObject(void); | ||
+ | |||
+ | public: | ||
+ | STDMETHODIMP QueryInterface(REFIID riid, void **ppv); | ||
+ | STDMETHODIMP_(ULONG) AddRef(void); | ||
+ | STDMETHODIMP_(ULONG) Release(void); | ||
+ | | ||
+ | STDMETHODIMP CreateInstance(IUnknown *pUnknownOuter, | ||
+ | STDMETHODIMP LockServer(BOOL bLock); | ||
+ | |||
+ | private: | ||
+ | LONG m_cRef; | ||
+ | }; | ||
+ | |||
+ | #endif // CALCULATORCLASS_H | ||
+ | </ | ||
+ | |||
+ | ==== calculatorclass.cpp ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | CalculatorClassObject:: | ||
+ | |||
+ | CalculatorClassObject:: | ||
+ | |||
+ | STDMETHODIMP CalculatorClassObject:: | ||
+ | if (riid == IID_IUnknown) { | ||
+ | *ppv = static_cast< | ||
+ | } else if (riid == IID_IClassFactory) { | ||
+ | *ppv = static_cast< | ||
+ | } else { | ||
+ | *ppv = nullptr; | ||
+ | return E_NOINTERFACE; | ||
+ | } | ||
+ | | ||
+ | reinterpret_cast< | ||
+ | return S_OK; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP_(ULONG) CalculatorClassObject:: | ||
+ | if (m_cRef == 0) { | ||
+ | LockModule(); | ||
+ | } | ||
+ | return InterlockedIncrement(& | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP_(ULONG) CalculatorClassObject:: | ||
+ | LONG res = InterlockedDecrement(& | ||
+ | if (res == 0) { | ||
+ | delete this; | ||
+ | UnlockModule(); | ||
+ | } | ||
+ | return res; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP CalculatorClassObject:: | ||
+ | if (pUnknownOuter != nullptr) { | ||
+ | return CLASS_E_NOAGGREGATION; | ||
+ | } | ||
+ | | ||
+ | Calculator *pCalculator = nullptr; | ||
+ | try { | ||
+ | pCalculator = new Calculator; | ||
+ | } catch (...) { | ||
+ | return E_OUTOFMEMORY; | ||
+ | } | ||
+ | | ||
+ | pCalculator-> | ||
+ | HRESULT hr = pCalculator-> | ||
+ | pCalculator-> | ||
+ | return hr; | ||
+ | } | ||
+ | |||
+ | STDMETHODIMP CalculatorClassObject:: | ||
+ | //if (bLock) { | ||
+ | // LockModule(); | ||
+ | //} else { | ||
+ | // UnlockModule(); | ||
+ | //} | ||
+ | return S_OK; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== modulelock.h ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #ifndef MOUDLELOCK_H | ||
+ | #define MODULELOCK_H | ||
+ | |||
+ | #include < | ||
+ | |||
+ | void LockModule(); | ||
+ | void UnlockModule(); | ||
+ | LONG GetModuleLockCount(); | ||
+ | |||
+ | #endif // MODULELOCK_H | ||
+ | </ | ||
+ | |||
+ | ==== modulelock.cpp ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | |||
+ | static LONG g_cLocks = 0; | ||
+ | |||
+ | void LockModule() { | ||
+ | InterlockedIncrement(& | ||
+ | } | ||
+ | |||
+ | void UnlockModule() { | ||
+ | InterlockedDecrement(& | ||
+ | } | ||
+ | |||
+ | LONG GetModuleLockCount() { | ||
+ | return g_cLocks; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== exports.cpp ===== | ||
+ | |||
+ | <file cpp> | ||
+ | #include " | ||
+ | #include " | ||
+ | // #include < | ||
+ | // #include < | ||
+ | // #include < | ||
+ | // #include < | ||
+ | |||
+ | extern IID const LIBID_ToymathLib3; | ||
+ | extern CLSID const CLSID_Calculator; | ||
+ | |||
+ | static WCHAR const *g_wszModulePath = L" | ||
+ | static WCHAR const *g_wszProgId = L" | ||
+ | |||
+ | using RegKV = std:: | ||
+ | |||
+ | //static HRESULT RegisterServerWriteRegistry(RegKV const &kv) { | ||
+ | // HKEY hkey; | ||
+ | // if (long err = RegCreateKeyW(HKEY_CLASSES_ROOT, | ||
+ | // err = RegSetValueW(hkey, | ||
+ | // RegCloseKey(hkey); | ||
+ | // if (err == ERROR_SUCCESS) { | ||
+ | // return S_OK; | ||
+ | // } | ||
+ | // } | ||
+ | // return SELFREG_E_CLASS; | ||
+ | //} | ||
+ | |||
+ | STDAPI DllGetClassObject(CLSID const &clsid, IID const &iid, void **ppv) { | ||
+ | if (clsid != CLSID_Calculator) { | ||
+ | return CLASS_E_CLASSNOTAVAILABLE; | ||
+ | } | ||
+ | | ||
+ | CalculatorClassObject *pCalculatorClass = nullptr; | ||
+ | try { | ||
+ | pCalculatorClass = new CalculatorClassObject; | ||
+ | } catch (...) { | ||
+ | return E_OUTOFMEMORY; | ||
+ | } | ||
+ | | ||
+ | pCalculatorClass-> | ||
+ | HRESULT hr = pCalculatorClass-> | ||
+ | pCalculatorClass-> | ||
+ | return hr; | ||
+ | } | ||
+ | |||
+ | STDAPI DllCanUnloadNow() { | ||
+ | if (GetModuleLockCount() == 0) { | ||
+ | return S_OK; | ||
+ | } else { | ||
+ | return S_FALSE; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | STDAPI DllRegisterServer(void) { | ||
+ | return E_NOTIMPL; | ||
+ | | ||
+ | // ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ | ||
+ | // この関数では、レジストリにモジュールの情報を登録します。 | ||
+ | // レジストリの操作は、ちょっとしたミスでシステムを破壊してしまう危険が伴います。 | ||
+ | // 何が行われるかを完全に理解していない限り実行をしないでください。 | ||
+ | // もし試すのであれば、壊れても被害の少ない実験用の環境で試すことを強くおすすめします。 | ||
+ | // 必ずトラブルが発生しても復旧できるように復元ポイントを作成しておいてください。 | ||
+ | // | ||
+ | // サンプルをあげておきます。 | ||
+ | // 正しく動作することは一切保証できません。 | ||
+ | // 不用意に実行しないでください。 | ||
+ | // ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ | ||
+ | | ||
+ | // LPOLESTR lpstrClsid; | ||
+ | // StringFromCLSID(CLSID_Calculator, | ||
+ | // RegKV clsid = {std:: | ||
+ | // RegKV inproc = {std:: | ||
+ | // RegKV progid = {std:: | ||
+ | // RegKV hkcrProgid = {std:: | ||
+ | // RegKV hkcrProgidClsid = {std:: | ||
+ | // CoTaskMemFree(lpstrClsid); | ||
+ | // | ||
+ | // if (HRESULT hr = RegisterServerWriteRegistry(clsid); | ||
+ | // return hr; | ||
+ | // } | ||
+ | // if (HRESULT hr = RegisterServerWriteRegistry(inproc); | ||
+ | // return hr; | ||
+ | // } | ||
+ | // if (HRESULT hr = RegisterServerWriteRegistry(progid); | ||
+ | // return hr; | ||
+ | // } | ||
+ | // // HKCR\Toymath3.Calculator.1 | ||
+ | // if (HRESULT hr = RegisterServerWriteRegistry(hkcrProgid); | ||
+ | // return hr; | ||
+ | // } | ||
+ | // // HKCR\Toymath3.Calculator.1\CLSID | ||
+ | // if (HRESULT hr = RegisterServerWriteRegistry(hkcrProgidClsid); | ||
+ | // return hr; | ||
+ | // } | ||
+ | // | ||
+ | // ITypeLib *ptlib; | ||
+ | // HRESULT hr = LoadTypeLib(g_wszModulePath, | ||
+ | // if (SUCCEEDED(hr)) { | ||
+ | // hr = RegisterTypeLib(ptlib, | ||
+ | // ptlib-> | ||
+ | // } | ||
+ | // return hr; | ||
+ | } | ||
+ | |||
+ | STDAPI DllUnregisterServer(void) { | ||
+ | return E_NOTIMPL; | ||
+ | |||
+ | // ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ | ||
+ | // この関数では、レジストリから登録されているモジュールの情報を削除します。 | ||
+ | // レジストリの操作は、ちょっとしたミスでシステムを破壊してしまう危険が伴います。 | ||
+ | // 何が行われるかを完全に理解していない限り実行をしないでください。 | ||
+ | // もし試すのであれば、壊れても被害の少ない実験用の環境で試すことを強くおすすめします。 | ||
+ | // 必ずトラブルが発生しても復旧できるように復元ポイントを作成しておいてください。 | ||
+ | // | ||
+ | // サンプルをあげておきます。 | ||
+ | // 正しく動作することは一切保証できません。 | ||
+ | // 不用意に実行しないでください。 | ||
+ | // ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ | ||
+ | | ||
+ | // HRESULT hr = UnRegisterTypeLib(LIBID_ToymathLib3, | ||
+ | // | ||
+ | // LPOLESTR lpstrClsid; | ||
+ | // StringFromCLSID(CLSID_Calculator, | ||
+ | // std:: | ||
+ | // std:: | ||
+ | // std:: | ||
+ | // std:: | ||
+ | // std:: | ||
+ | // CoTaskMemFree(lpstrClsid); | ||
+ | // | ||
+ | // if (RegDeleteKeyW(HKEY_CLASSES_ROOT, | ||
+ | // hr = E_FAIL; | ||
+ | // } | ||
+ | // if (RegDeleteKeyW(HKEY_CLASSES_ROOT, | ||
+ | // hr = E_FAIL; | ||
+ | // } | ||
+ | // if (RegDeleteKeyW(HKEY_CLASSES_ROOT, | ||
+ | // hr = E_FAIL; | ||
+ | // } | ||
+ | // if (RegDeleteKeyW(HKEY_CLASSES_ROOT, | ||
+ | // hr = E_FAIL; | ||
+ | // } | ||
+ | // if (RegDeleteKeyW(HKEY_CLASSES_ROOT, | ||
+ | // hr = E_FAIL; | ||
+ | // } | ||
+ | // | ||
+ | // return hr; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== toymath3.idl ===== | ||
+ | |||
+ | <file cpp> | ||
+ | import " | ||
+ | |||
+ | [object, uuid(1dc508ef-d0eb-420a-b213-dd16aa0dfee0)] | ||
+ | interface ICalculator : IUnknown { | ||
+ | HRESULT Add([in] long x, [in] long y, [out, retval] long *result); | ||
+ | HRESULT Sub([in] long x, [in] long y, [out, retval] long *result); | ||
+ | HRESULT Mul([in] long x, [in] long y, [out, retval] long *result); | ||
+ | HRESULT Div([in] long x, [in] long y, [out, retval] long *result); | ||
+ | } | ||
+ | |||
+ | [ | ||
+ | uuid(f90bdc34-89b3-46dd-b262-edf4aba3a935), | ||
+ | lcid(0), | ||
+ | version(1.0), | ||
+ | helpstring(" | ||
+ | ] | ||
+ | library ToymathLib3 { | ||
+ | importlib(" | ||
+ | |||
+ | [uuid(957E455A-8FD1-4D33-8057-462897B00888)] | ||
+ | coclass Calculator { | ||
+ | [default] interface ICalculator; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== toymath3.rc ===== | ||
+ | |||
+ | < | ||
+ | 1 | ||
+ | </ | ||