Golang으로 윈도우DLL 만들고 C#에서 사용하기

Golang으로 DLL 만드는거 한번 해봄. 이렇게 만든 dll은 다른 언어에서 사용가능한데 예제를 여기에 정리해봄.

package main

import (
    "C"
    "fmt"
)

//export test1
func test1() {
    fmt.Println("===============================")
    fmt.Println("테스트1")
    a := 3
    b := 5

    fmt.Println("a+b=", a+b)
}

//export test2
func test2(a int, b float64) float64 {
    fmt.Println("===============================")
    fmt.Println("테스트2")
    fmt.Println(a, "+", b, "=", float64(a)+b)
    return (float64(a) + b)
}

//export test3
func test3(arg *C.char) *C.char {
    fmt.Println("===============================")
    fmt.Println("테스트3")
    input := C.GoString(arg)
    fmt.Println("입력값은", input, "입니다.")
    return C.CString("반환값은 " + input + " 입니다")
}

func main() {
}

3가지 함수를 만들어서 dll로 뽑아낸다.

golang에서 dll 만들때 주의점이라면 뽑아낼 함수 위에 주석으로 //export 함수명 적어줘야 한다는것이다. (/* */ 주석으론 안됨, // 랑 export 사이에 공백있어도 안됨)
이거 때문에 삽질 좀 했음 에러가 나는게 아니라 export 자체가 안되니…

맨 밑에 main()는 컴파일 하는데 필요하다. 그냥 공백으로 해서 넣어준다.

dll로 빌드하는법은

//go build -o 뽑아낼dll이름 -buildmode=c-shared 빌드할go파일
ex) go build -o testDLL.dll -buildmode=c-shared .testDLL.go

이렇게 빌드된 dll파일을 c#프로젝트 폴더에 실행파일 위치 (테스트는 debug 폴더)에 복사한다.

 

C# 프로젝트를 하나 만들고 아래와 같은 코드를 넣어준다.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2 {
    class Program {
        //---------------------------------------------------------------------------------------------------
        [DllImport("testDLL.dll")]
        public static extern void test1();
        [DllImport("testDLL.dll")]
        public static extern double test2(int a, double b);

        [DllImport("testDLL.dll")]
        public static extern IntPtr test3(byte[] str);
        //---------------------------------------------------------------------------------------------------

        static unsafe string MarshalUtf8ToUnicode(IntPtr pStringUtf82) {
            var pStringUtf8 = (byte*)pStringUtf82;
            var len = 0;
            while (pStringUtf8[len] != 0) 
                len++;
            return Encoding.UTF8.GetString(pStringUtf8, len);
        }
        static void Main(string[] args) {

            test1();

            var ret1 = test2(3, 0.8f);
            Console.WriteLine(ret1);

            var pStr = test3(Encoding.UTF8.GetBytes("탕수육"));
            string str = MarshalUtf8ToUnicode(pStr);
            Console.WriteLine(str);
        }
    }
}

golang은 내부적으로 문자열 처리를 UTF-8로 처리하고 c#은 unicode로 처리 하기 때문에 호출할때 문자열을 UTF-8로 변환해서 넣어주고
리턴받은 값은 unicode로 변환해서 처리한다.

덤으로 dll빌드할때 기본값으론 SDK 32비트64비트 따라서 빌드 되는데 c# 기본 플젝 생성하면 Any CPU로 되어있는데

이걸 x64로 바꿔줘야지만 정상작동한다.


Comments

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다