Last active
June 2, 2019 06:53
-
-
Save luncliff/50b2ce1158d7309ac995c6cf343c9bfe to your computer and use it in GitHub Desktop.
Short practice for using Windows DLL in Go Language
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// | |
// References | |
// - https://medium.com/jettech/breaking-all-the-rules-using-go-to-call-windows-api-2cbfd8c79724 | |
// | |
import ( | |
"math/rand" | |
"os" | |
"path/filepath" | |
"plugin" | |
"runtime" | |
"syscall" | |
"testing" | |
) | |
func testDllPath() string { | |
name := "module1.dll" | |
wd, _ := os.Getwd() | |
mpath := filepath.Join(wd, "build", "Debug", name) | |
return mpath | |
} | |
func TestTryLoadWithPath(t *testing.T) { | |
mpath := testDllPath() | |
if _, err := plugin.Open(mpath); err != nil { | |
t.Log(err) // this can fail if not implemented | |
} | |
} | |
func TestSyscallWindowsDLL(t *testing.T) { | |
if runtime.GOOS != "windows" { | |
t.SkipNow() | |
} | |
mpath := testDllPath() | |
p, err := syscall.LoadDLL(mpath) | |
if err != nil { | |
t.Fatal(err) | |
} | |
defer p.Release() | |
t.Log("handle", p.Handle) | |
fn, err := p.FindProc("is_available") | |
if err != nil { | |
t.Fatal(err) | |
} | |
t.Logf("proc %s %x", fn.Name, fn.Addr()) | |
arg0 := uint32(16) | |
ret1, _, err := fn.Call(uintptr(arg0)) | |
if err != syscall.Errno(0) { | |
t.Log(err) | |
} | |
t.Log(ret1, ":=", fn.Name, "(", arg0, ")") | |
} | |
func TestSyscallParallel(t *testing.T) { | |
if runtime.GOOS != "windows" { | |
t.SkipNow() | |
} | |
mpath := testDllPath() | |
p, err := syscall.LoadDLL(mpath) | |
if err != nil { | |
t.Fatal(err) | |
} | |
defer p.Release() | |
fn, err := p.FindProc("is_available") | |
if err != nil { | |
t.Fatal(err) | |
} | |
requests := make(chan uint32, 10) | |
defer close(requests) | |
serve := func(arg0 uint32) (uintptr, error) { | |
ret1, _, err := fn.Call(uintptr(arg0)) | |
if err != syscall.Errno(0) { | |
return ret1, err | |
} | |
return ret1, nil | |
} | |
worker := func(id uint32, reqs <-chan uint32) { | |
for req := range reqs { | |
ret, err := serve(req) | |
if err != nil { | |
t.Log(id, "failed", err) | |
} else { | |
t.Log(id, ret, "<--", req) | |
} | |
} | |
} | |
go worker(0xA, requests) | |
go worker(0xB, requests) | |
go worker(0xC, requests) | |
go worker(0xD, requests) | |
for i := 0; i < 50; i++ { | |
requests <- rand.Uint32() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmake_minimum_required(VERSION 3.14) | |
project(module1 LANGUAGES CXX) | |
add_library(module1 SHARED | |
cpp_export.h | |
cpp_libmain.cpp | |
cpp_export_c.cpp | |
) | |
set_target_properties(module1 | |
PROPERTIES | |
CXX_STANDARD 20 | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
// clang-format off | |
# if defined(_MSC_VER) // MSVC | |
# define _HIDDEN_ | |
# ifdef _WINDLL | |
# define _INTERFACE_ __declspec(dllexport) | |
# else | |
# define _INTERFACE_ __declspec(dllimport) | |
# endif | |
# elif defined(__GNUC__) || defined(__clang__) | |
# define _INTERFACE_ __attribute__((visibility("default"))) | |
# define _HIDDEN_ __attribute__((visibility("hidden"))) | |
# else | |
# error "unexpected compiler" | |
# endif // compiler check | |
// clang-format on | |
#include <cstdint> | |
namespace space1 | |
{ | |
_INTERFACE_ bool is_available(uint32_t idx) noexcept; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cpp_export.h" | |
extern "C" | |
{ | |
_INTERFACE_ uint32_t is_available(uint32_t idx) noexcept | |
{ | |
return space1::is_available(idx); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "cpp_export.h" | |
namespace space1 | |
{ | |
bool is_available(uint32_t idx) noexcept | |
{ | |
return idx < 4; | |
} | |
} // namespace space1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Exported symbols in DLL with https://github.com/lucasg/Dependencies