Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build: 移除并未链接的库, 将部分静态链接的库改为运行时加载,显式链接 #159

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -918,7 +918,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
Loading