CGO 之 Dll调用

生成的dll库代码

// GoDll.cpp : 定义 DLL 应用程序的导出函数。
//
 
#include "stdafx.h"
#include <iostream>
#include <cstdint>
 
void  __stdcall void_R0()
{
	std::cout << __FUNCTION__ << std::endl;
}
 
 
void  __stdcall void_R1(const char* name)
{
	std::cout << __FUNCTION__ << " ----> " << name << std::endl;
}
 
 
void  __stdcall void_R2(const char*name ,char **outName)
{
	std::string _name = "HintSoft 新浩艺-";
	_name += name;
	strcpy(*outName,_name.c_str());
}
 
 
uint8_t __stdcall uint8_R1(char** outJson)
{
	*outJson = new char[256];
	memset(*outJson,0,256);
	strcpy(*outJson,"Hello -> 你被骗了,这里没有Json,只有中文");
	return 1;
}
 
void __stdcall uint8_R1_free(char** outJson)
{
	if(outJson == 0) return;
 
	if(*outJson == 0) return;
 
	delete [](*outJson);
	*outJson = nullptr;
}
 
typedef void (*CallBackFunType)(const char * in);
void setCallBackFun(CallBackFunType func)
{
	if(!func)
	{
		std::cout << __FUNCTION__ << "   NULL ptr" << std::endl;
	}
 
	func("hello CallBackFuncType  ---- setCallBackFun");
}

  

导出函数def,vs里新建一个*.def后缀名的文件,添加下面:

EXPORTS
void_R0						@1
void_R1						@2
void_R2						@3
uint8_R1					@4
uint8_R1_free				        @5
setCallBackFun				        @6

  

go调用测试:

package main
 
import (
	"fmt"
	"syscall"
	"unsafe"
)
 
/*
#include <stdio.h>   // 如果要调用C.free 一定要在些包含对应的头文件
#include <stdlib.h>
// 以下两种方式任选其一
void CallBackFun( char* in);
//void CallBackFun( char* in)
//{
//	printf("%s\r\n",in);
//}
*/
import "C"
 
// export 必须要
//export CallBackFun
func CallBackFun(in *C.char) {
	fmt.Print(C.GoString(in))
}
 
func main() {
	fmt.Println("---------------------------------------------------------------")
 
	handle, err := syscall.LoadDLL("GoDll.dll")
	if err != nil {
		fmt.Println(err.Error())
		return
	}
 
	fmt.Println(handle.Handle)
	fmt.Println(handle.Name)
 
	void_R0, err := handle.FindProc("void_R0")
	if err != nil {
		fmt.Println("void_R0 不存在", err.Error())
		return
	}
 
	void_R1, err := handle.FindProc("void_R1")
	if err != nil {
		fmt.Println("void_R1 不存在", err.Error())
		return
	}
 
	void_R2, err := handle.FindProc("void_R2")
	if err != nil {
		fmt.Println("void_R2 不存在", err.Error())
		return
	}
 
	uint8_R1, err := handle.FindProc("uint8_R1")
	if err != nil {
		fmt.Println("uint8_R1 不存在", err.Error())
		return
	}
 
	uint8_R1_free, err := handle.FindProc("uint8_R1_free")
	if err != nil {
		fmt.Println("uint8_R1_free 不存在", err.Error())
		return
	}
 
	setCallBackFun, err := handle.FindProc("setCallBackFun")
	if err != nil {
		fmt.Println("setCallBackFun 不存在", err.Error())
		return
	}
 
	fmt.Println("--------------------------函数加载成功-------------------------")
	// -------------------------------------------------------------------------
	fmt.Println("---- void_R0")
	fmt.Println(void_R0.Addr())
	void_R0.Call()
	// -------------------------------------------------------------------------
	fmt.Println("\r\n\r\n---- void_R1")
	fmt.Println(void_R1.Addr())
	name := C.CString("li_jian_xing")
	void_R1.Call((uintptr)(unsafe.Pointer(name)))
	C.free(unsafe.Pointer(name))
	// -------------------------------------------------------------------------
	// 创建数组,传入char** 取出C函数中的数据
	fmt.Println("\r\n\r\n---- void_R2")
	fmt.Println(void_R2.Addr())
	arg := make([]C.char, 1024)
	name = C.CString("li_jian_xing")
	void_R2.Call((uintptr)(unsafe.Pointer(name)), (uintptr)(unsafe.Pointer((&arg))))
	C.free(unsafe.Pointer(name))
	fmt.Println(C.GoString(&arg[0]))
	// -------------------------------------------------------------------------
	// 传入char** 取出C函数分配的内存,处理完再释放
	fmt.Println("\r\n\r\n---- uint8_R1")
	fmt.Println(uint8_R1.Addr())
	var argc *C.char
	uint8_R1.Call((uintptr)(unsafe.Pointer(&argc)))
	fmt.Println(C.GoString(argc))
	uint8_R1_free.Call((uintptr)(unsafe.Pointer(&argc)))
	// -------------------------------------------------------------------------
	// 向dll 函数设定回调
	fmt.Println("\r\n\r\n---- setCallBackFun")
	fmt.Println(setCallBackFun.Addr())
 
	setCallBackFun.Call((uintptr)(unsafe.Pointer(C.CallBackFun)))
 
	handle.Release() // 释放dll 句柄
 
}

  

 

posted on 2018-08-13 17:05  子墨'  阅读(1565)  评论(0编辑  收藏  举报

导航