Home >Backend Development >Golang >How to implement DllMain function using Golang

How to implement DllMain function using Golang

PHPz
PHPzOriginal
2023-04-06 09:11:231113browse

Under the Windows platform, the Dynamic Link Library (DLL) is a commonly used componentization technology. It allows multiple programs to share the same function library, reducing the development of duplicate code, and can achieve Module upgrade, replacement and other operations. When writing a DLL, DllMain is the most important function. This article will explore how to use Golang to implement the DllMain function.

1. Overview of DllMain

On the Windows platform, when the DLL is loaded or unloaded, the operating system will automatically call the DllMain function. The prototype of the DllMain function is as follows:

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpReserved);

Among them, the hinstDll parameter is the instance handle of the DLL itself, and the fdwReason parameter indicates the reason why the DLL is loaded, unloaded or other operations, and can take the following values:

  • DLL_PROCESS_ATTACH: Called when the DLL is loaded
  • DLL_PROCESS_DETACH: Called when the DLL is unloaded
  • DLL_THREAD_ATTACH: Called when the thread is created
  • DLL_THREAD_DETACH: Called when the thread ends

lpReserved is not used and remains NULL.

In the DllMain function, some initialization and cleanup work can be completed, such as registering and unregistering COM components, etc. In addition, it should be noted that calling some functions in DllMain may cause deadlock or other problems. It is generally not recommended to do too much work in the DllMain function, only do necessary initialization and cleanup.

2. Use Golang to implement DllMain

Golang is a fast and efficient programming language, and can output a C language dynamic link library, so you can use Golang to implement the DllMain function.

First, we need to tell Golang to output the dynamic link library. You can use the following command:

go build -buildmode=c-shared -o example.dll example.go

Among them, example.go is the Golang code file we wrote, and example.dll is the output dynamic link. Library file.

Next, we need to implement the DllMain function in the Golang code. Since Golang is a static language and does not support pointer operations and raw pointers in C language, you need to use a C language interpreter to call Golang functions through C language code. Specifically, we can connect C language code and Golang code through the #cgo directive. The following is an example:

package main

import "C"

var (
    hInstance C.HMODULE
)

//export DllMain
func DllMain(hinstDLL C.HMODULE, fdwReason C.DWORD, lpvReserved C.LPVOID) C.BOOL {
    switch fdwReason {
    case C.DLL_PROCESS_ATTACH:
        hInstance = hinstDLL
        // do initialize job here

    case C.DLL_PROCESS_DETACH:
        // do cleanup job here

    case C.DLL_THREAD_ATTACH:
        // do something when a new thread created

    case C.DLL_THREAD_DETACH:
        // do something when a thread was ended
    }

    return 1
}

In this example, we define an external variable hInstance and assign the DLL handle to it in the DllMain function. We can complete the initialization and cleanup work in the DllMain function, and add other processing logic as needed. Note that due to Golang's memory management mechanism, if you need to use Golang objects in DllMain, you need to ensure that their life cycle does not exceed the scope of the DllMain function.

3. Compile and test

After writing the Golang code, we need to compile it and test it. On the Windows platform, we can use Visual Studio's built-in "Visual Studio Native Tools Command Prompt" command prompt, enter the cmd window in the project directory, and run the following command:

set CGO_ENABLED=1
set CGO_CFLAGS=-Wall
go build -buildmode=c-shared -o example.dll example.go

Among them, CGO_ENABLED means that it can be used C language interpreter, CGO_CFLAGS indicates compilation options, -Wall indicates turning on all warnings. The go build command compiles Golang code into a DLL file.

After compilation is completed, we can use Visual Studio to create a console application, and then load and unload the dynamic link library by calling the LoadLibrary and UnloadLibrary functions to test whether the DllMain function is called. For specific test examples, please refer to the following code:

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

typedef BOOL(WINAPI* DllMainFunc)(HINSTANCE, DWORD, LPVOID);

int main() {
    HMODULE hDll = LoadLibrary("example.dll");

    if (hDll == NULL) {
        printf("Load library failed.\n");
    }
    else {
        printf("Load library succeed.\n");

        DllMainFunc pDllMain = (DllMainFunc)GetProcAddress(hDll, "DllMain");

        if (pDllMain == NULL) {
            printf("Get function address failed.\n");
        }
        else {
            printf("Get function address succeed.\n");
            (*pDllMain)(hDll, DLL_PROCESS_ATTACH, NULL);
            (*pDllMain)(hDll, DLL_PROCESS_DETACH, NULL);
        }

        FreeLibrary(hDll); 
    }

    return 0;
}

After running the test program, we can see the console output "Load library succeed." and "Get function address succeed.", indicating that loading and finding function addresses work normally. , and no error occurred when calling the DllMain function.

4. Summary

This article briefly introduces the concept and purpose of the DllMain function, and then takes Golang as an example to describe how to use Golang to implement the DllMain function. Although Golang is an efficient programming language, it is not suitable for all scenarios. You need to choose the appropriate language and technology stack after weighing the pros and cons.

The above is the detailed content of How to implement DllMain function using Golang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn