Skip to content

Commit

Permalink
build: 移除并未链接的库, 将部分静态链接的库改为运行时加载,显式链接 (#159)
Browse files Browse the repository at this point in the history
  • Loading branch information
yixy-only authored Apr 30, 2024
1 parent 86faf1b commit b78a205
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 59 deletions.
6 changes: 0 additions & 6 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,4 @@ endif ()
target_link_libraries(xege
INTERFACE gdiplus
INTERFACE gdi32
INTERFACE imm32
INTERFACE msimg32
INTERFACE ole32
INTERFACE oleaut32
INTERFACE uuid
INTERFACE winmm
)
1 change: 1 addition & 0 deletions src/ege_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ege_math.h"
#include "ege_time.h"
#include "ege_graph.h"
#include "ege_dllimport.h"

#include "type.h"
#include "utils.h"
Expand Down
314 changes: 314 additions & 0 deletions src/ege_dllimport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
#include "ege_dllimport.h"

#include <windef.h>
#include <windows.h>
#include <stdio.h>


#define LOG(logtext) \
do \
{ \
fprintf(stderr, "%s\n", (logtext)); \
} while (0)

#define LOG_IF(express, logtext) \
do \
{ \
if (!!(express)) { \
LOG(logtext); \
} \
} while (0)

namespace dll
{
// ----------------------------- imm32.dll ------------------------------------
static HMODULE imm32Dll;
static HIMC (*func_ImmGetContext)(HWND);
static BOOL (*func_ImmSetCompositionWindow)(HIMC , LPCOMPOSITIONFORM);

static void initImm32Dll()
{
imm32Dll = NULL;
func_ImmGetContext = NULL;
func_ImmSetCompositionWindow = NULL;
}

static bool loadImm32Dll()
{
if(imm32Dll == NULL) {
imm32Dll = LoadLibraryA("imm32.dll");
if (imm32Dll == NULL) {
LOG("ege error: Failed to load imm32.dll.");
return false;
}
}

// ImmGetContext
if (func_ImmGetContext == NULL) {
typedef HIMC (*ImmGetContext_FuncType)(HWND);
func_ImmGetContext = (ImmGetContext_FuncType)GetProcAddress(imm32Dll, "ImmGetContext");
LOG_IF(func_ImmGetContext == NULL,"ege error: The 'ImmGetContext' function cannot be found from the imm32.dll.");
}

// ImmSetCompositionWindow
if (func_ImmSetCompositionWindow == NULL) {
typedef BOOL (*ImmSetCompositionWindow_FuncType)(HIMC, LPCOMPOSITIONFORM);
func_ImmSetCompositionWindow = (ImmSetCompositionWindow_FuncType)GetProcAddress(imm32Dll, "ImmSetCompositionWindow");
LOG_IF(func_ImmSetCompositionWindow == NULL, "ege error: The 'ImmSetCompositionWindow' function cannot be found from the imm32.dll.");
}

return func_ImmGetContext && func_ImmSetCompositionWindow;
}

HIMC ImmGetContext(HWND hwnd)
{
if (func_ImmGetContext) {
return func_ImmGetContext(hwnd);
}
return NULL;
}

BOOL ImmSetCompositionWindow(HIMC imc, LPCOMPOSITIONFORM compositionForm)
{
if (func_ImmSetCompositionWindow) {
return func_ImmSetCompositionWindow(imc, compositionForm);
}

return FALSE;
}

// ----------------------------- msimg32.dll ----------------------------------
static HMODULE msimg32Dll;
static BOOL (*func_AlphaBlend)(HDC hdcDest,int xoriginDest,int yoriginDest,int wDest,int hDest,HDC hdcSrc,int xoriginSrc,int yoriginSrc,int wSrc,int hSrc,BLENDFUNCTION ftn);
static BOOL (*func_GradientFill)(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode);

static void initMsimg32Dll()
{
msimg32Dll = NULL;
func_AlphaBlend = NULL;
func_GradientFill = NULL;
}

static bool loadMsimg32Dll()
{
// -- msimg32.dll --
if (msimg32Dll == NULL) {
msimg32Dll = LoadLibraryA("msimg32.dll");
if (msimg32Dll == NULL) {
LOG("ege error: Failed to load msimg32.dll.");
return false;
}
}

// AlphaBlend
if (func_AlphaBlend == NULL) {
typedef BOOL (*AlphaBlend_FuncType)(HDC hdcDest,int xoriginDest,int yoriginDest,int wDest,int hDest,HDC hdcSrc,int xoriginSrc,int yoriginSrc,int wSrc,int hSrc,BLENDFUNCTION ftn);
func_AlphaBlend = (AlphaBlend_FuncType)GetProcAddress(msimg32Dll, "AlphaBlend");
LOG_IF(func_AlphaBlend == NULL,"ege error: The 'AlphaBlend' function cannot be found from the msimg32.dll.");
}

// GradientFill
if (func_GradientFill == NULL) {
typedef BOOL (*GradientFill_FuncType)(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode);
func_GradientFill = (GradientFill_FuncType)GetProcAddress(msimg32Dll, "GradientFill");
LOG_IF(func_GradientFill == NULL, "ege error: The 'GradientFill' function cannot be found from the msimg32.dll.");
}

return func_AlphaBlend && func_GradientFill;
}

BOOL AlphaBlend(HDC hdcDest,int xoriginDest,int yoriginDest,int wDest,int hDest,HDC hdcSrc,int xoriginSrc,int yoriginSrc,int wSrc,int hSrc,BLENDFUNCTION ftn)
{
if (func_AlphaBlend) {
return func_AlphaBlend(hdcDest, xoriginDest, yoriginDest, wDest, hDest, hdcSrc, xoriginSrc, yoriginSrc, wSrc, hSrc, ftn);
}
return FALSE;
}

BOOL GradientFill(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode)
{
if(func_GradientFill) {
return func_GradientFill(hdc, pVertex, nVertex, pMesh, nMesh, ulMode);
}
return FALSE;
}

// --------------------------------- winmm.dll -------------------------------------------
static HMODULE winmmDll;
static MMRESULT (*func_timeBeginPeriod)(UINT uPeriod);
static MMRESULT (*func_timeEndPeriod)(UINT uPeriod);
static MMRESULT (*func_timeSetEvent)(UINT uDelay,UINT uResolution,LPTIMECALLBACK fptc,DWORD_PTR dwUser,UINT fuEvent);
static MMRESULT (*func_timeKillEvent)(UINT uTimerID);
static MCIERROR (*func_mciSendCommandW)(MCIDEVICEID mciId,UINT uMsg,DWORD_PTR dwParam1,DWORD_PTR dwParam2);

static void initWinmmDll()
{
winmmDll = NULL;
func_timeBeginPeriod = NULL;
func_timeEndPeriod = NULL;
func_timeSetEvent = NULL;
func_timeKillEvent = NULL;
func_mciSendCommandW = NULL;
}

static bool loadWinmmDll()
{
// winmm.dll
if (winmmDll == NULL) {
winmmDll = LoadLibraryA("winmm.dll");
if (winmmDll == NULL) {
LOG("ege error: Failed to load winmm.dll.");
return false;
}
}

// timeBeginPeriod
if (func_timeBeginPeriod == NULL) {
typedef MMRESULT (*timeBeginPeriod_FuncType)(UINT uPeriod);
func_timeBeginPeriod = (timeBeginPeriod_FuncType)GetProcAddress(winmmDll, "timeBeginPeriod");
LOG_IF(func_timeBeginPeriod == NULL, "ege error: The 'timeBeginPeriod' function cannot be found from the winmm.dll.");
}

// timeEndPeriod
if (func_timeEndPeriod == NULL) {
typedef MMRESULT (*timeEndPeriod_FuncType)(UINT uPeriod);
func_timeEndPeriod = (timeEndPeriod_FuncType)GetProcAddress(winmmDll, "timeEndPeriod");
LOG_IF(func_timeEndPeriod == NULL, "ege error: The 'timeEndPeriod' function cannot be found from the winmm.dll.");
}


// timeSetEvent
if (func_timeSetEvent == NULL) {
typedef MMRESULT (*timeSetEvent_FuncType)(UINT uDelay,UINT uResolution,LPTIMECALLBACK fptc,DWORD_PTR dwUser,UINT fuEvent);
func_timeSetEvent = (timeSetEvent_FuncType)GetProcAddress(winmmDll, "timeSetEvent");
LOG_IF(func_timeSetEvent == NULL, "ege error: The 'timeSetEvent' function cannot be found from the winmm.dll.");
}

// timeKillEvent
if (func_timeKillEvent == NULL) {
typedef MMRESULT (*timeKillEvent_FuncType)(UINT uTimerID);
func_timeKillEvent = (timeKillEvent_FuncType)GetProcAddress(winmmDll, "timeKillEvent");
LOG_IF(func_timeKillEvent == NULL, "ege error: The 'timeKillEvent' function cannot be found from the winmm.dll.");
}


// mciSendCommandW
if (func_mciSendCommandW == NULL) {
typedef MCIERROR (*mciSendCommandW_FuncType)(MCIDEVICEID mciId,UINT uMsg,DWORD_PTR dwParam1,DWORD_PTR dwParam2);
func_mciSendCommandW = (mciSendCommandW_FuncType)GetProcAddress(winmmDll, "mciSendCommandW");
LOG_IF(func_mciSendCommandW == NULL, "ege error: The 'mciSendCommandW' function cannot be found from the winmm.dll.");
}

return func_timeBeginPeriod && func_timeEndPeriod && func_timeSetEvent && func_timeKillEvent && func_mciSendCommandW;
}

MMRESULT timeBeginPeriod(UINT uPeriod)
{
if (func_timeBeginPeriod) {
return func_timeBeginPeriod(uPeriod);
}
return NULL;
}

MMRESULT timeEndPeriod(UINT uPeriod)
{
if (func_timeEndPeriod) {
func_timeEndPeriod(uPeriod);
}
return NULL;
}

MMRESULT timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK fptc,DWORD_PTR dwUser,UINT fuEvent)
{
if (func_timeSetEvent) {
return func_timeSetEvent(uDelay, uResolution, fptc, dwUser, fuEvent);
}

return NULL;
}

MMRESULT timeKillEvent(UINT uTimerID)
{
if (func_timeKillEvent) {
return func_timeKillEvent(uTimerID);
}

return NULL;
}

MCIERROR mciSendCommandW(MCIDEVICEID mciId,UINT uMsg,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
{
if (func_mciSendCommandW) {
return func_mciSendCommandW(mciId, uMsg, dwParam1, dwParam2);
}

return NULL;
}

// ----------------------------------------------------------------------------
// 加载 dll 以及需要的符号
void loadDllsIfNot()
{
static bool loadingIsFinished = false;
static bool firstCall = true; // 初次调用标记, 因不同编译单元初始化顺序未保证, 防止静态变量未初始化

if (firstCall) {
initImm32Dll();
initMsimg32Dll();
initWinmmDll();
firstCall = false;
}

if (!loadingIsFinished) {
bool isSuccessful = true;

isSuccessful = loadImm32Dll() && isSuccessful;
isSuccessful = loadMsimg32Dll() && isSuccessful;
isSuccessful = loadWinmmDll() && isSuccessful;

loadingIsFinished = isSuccessful;
}
}

// 释放所有加载的 dll (imm32.dll, msimg32.dll, winmm.dll)
void freeDlls()
{
if (imm32Dll != NULL) {
FreeLibrary(imm32Dll);
}

if (msimg32Dll != NULL) {
FreeLibrary(msimg32Dll);
}

if (winmmDll != NULL) {
FreeLibrary(winmmDll);
}
}

// 临时从 dll 中加载 CreateStreamOnHGlobal 函数并调用
HRESULT CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm)
{
HMODULE Ole32Dll = LoadLibraryA("Ole32.dll");
if (Ole32Dll == NULL) {
LOG("ege error: Failed to load Ole32.dll.");
return S_FALSE;
}

typedef HRESULT (*CreateStreamOnHGlobalFuncType) (HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);
CreateStreamOnHGlobalFuncType CreateStreamOnHGlobalFunc = (CreateStreamOnHGlobalFuncType)GetProcAddress(Ole32Dll, "CreateStreamOnHGlobal");

HRESULT result;
if (CreateStreamOnHGlobalFunc == NULL) {
LOG("ege error: The 'CreateStreamOnHGlobal' function cannot be found from the Ole32.dll.");
result = S_FALSE;
} else {
result = CreateStreamOnHGlobalFunc(hGlobal, fDeleteOnRelease, ppstm);
}

FreeLibrary(Ole32Dll);
return result;
}

}

31 changes: 31 additions & 0 deletions src/ege_dllimport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <Windows.h>
#include <windef.h>

namespace dll
{
// 如果没加载 dll 则进行加载
void loadDllsIfNot();

// 释放所有加载的 dll
void freeDlls();

// 临时从 dll 中加载 CreateStreamOnHGlobal 函数并调用
HRESULT CreateStreamOnHGlobal(HGLOBAL hGlobal, BOOL fDeleteOnRelease, LPSTREAM *ppstm);

// --------------------- imm32.dll -----------------------
HIMC ImmGetContext(HWND hwnd);
BOOL ImmSetCompositionWindow(HIMC,LPCOMPOSITIONFORM);

// --------------------- msimg32.dll ---------------------
BOOL AlphaBlend(HDC hdcDest,int xoriginDest,int yoriginDest,int wDest,int hDest,HDC hdcSrc,int xoriginSrc,int yoriginSrc,int wSrc,int hSrc,BLENDFUNCTION ftn);
BOOL GradientFill(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode);

// --------------------- winmm.dll -----------------------
MMRESULT WINAPI timeBeginPeriod(UINT uPeriod);
MMRESULT WINAPI timeEndPeriod(UINT uPeriod);
MMRESULT WINAPI timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK fptc,DWORD_PTR dwUser,UINT fuEvent);
MMRESULT WINAPI timeKillEvent(UINT uTimerID);
MCIERROR WINAPI mciSendCommandW(MCIDEVICEID mciId,UINT uMsg,DWORD_PTR dwParam1,DWORD_PTR dwParam2);
}
5 changes: 0 additions & 5 deletions src/ege_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@
#define GRADIENT_FILL_RECT_V 0x00000001
#define GRADIENT_FILL_TRIANGLE 0x00000002
#define GRADIENT_FILL_OP_FLAG 0x000000ff

extern "C"
{
WINGDIAPI BOOL WINAPI GradientFill(HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode);
}
#endif

namespace ege
Expand Down
2 changes: 1 addition & 1 deletion src/egegapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,7 +922,7 @@ void fillpoly_gradient(int numpoints, const ege_colpoint* polypoints, PIMAGE pim
tri[j].Vertex2 = j + 1;
tri[j].Vertex3 = j + 2;
}
::GradientFill(img->getdc(), vert, numpoints, tri, numpoints - 2, GRADIENT_FILL_TRIANGLE);
dll::GradientFill(img->getdc(), vert, numpoints, tri, numpoints - 2, GRADIENT_FILL_TRIANGLE);
free(tri);
}
free(vert);
Expand Down
Loading

0 comments on commit b78a205

Please sign in to comment.