성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>CLion으로 만든 Rust Win32 DLL을 C#과 연동</h1> <p> 우선, CLion에서 rust를 사용하기 위해서는,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > CLion - Rust ; <a target='tab' href='https://www.jetbrains.com/help/clion/rust-support.html#install'>https://www.jetbrains.com/help/clion/rust-support.html#install</a> Rustup ; <a target='tab' href='https://rustup.rs/'>https://rustup.rs/</a> </pre> <br /> <a target='tab' href='https://win.rustup.rs/x86_64'>rustup-init.exe</a>를 다운로드해 실행부터 해줍니다. 그럼 %USERPROFILE%\.cargo\bin 디렉터리에 rust 환경이 구축되는데요, 따라서 편의상 환경변수 PATH 설정에 해당 경로를 추가하는 것을 권장합니다.<br /> <br /> 그다음 CLion의 Plugins를 통해 "<a target='tab' href='https://plugins.jetbrains.com/plugin/22407-rust'>Rust</a>" 확장을 설치하면 준비는 끝입니다. 참고로, Visual Studio와 함께 C++ 구성요소를 미리 설치해 두는 것이 좋습니다. 왜냐하면 나중에 Rust 프로젝트를 처음 생성하는 시점에 시스템의 C/C++ 컴파일러를 설정하는 옵션이 뜰 텐데, 그때 Visual C++ 환경을 선택해 주면 됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 문법 공부는 천천히 시간 나는 대로 아래의 사이트를 통해 하시고, ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The Rust Programming Language (번역본) ; <a target='tab' href='https://doc.rust-kr.org/'>https://doc.rust-kr.org/</a> </pre> <br /> 곧바로 실습을 위해 CLion으로 다음과 같이 Rust Library 프로젝트를 생성하면,<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='rust_dll_prj_1.png' src='/SysWebRes/bbs/rust_dll_prj_1.png' /><br /> <br /> 기본적으로 ./src/lib.rs 파일이 생성되고 아래의 내용을 갖습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > pub fn add(left: usize, right: usize) -> usize { left + right } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let result = add(2, 2); assert_eq!(result, 4); } } </pre> <br /> (CLion을 통해 생성한 프로젝트 구조는 명령행에서 "cargo new testapp2 --lib"를 실행한 것과 같습니다.)<br /> <br /> CLion은 라이브러리 프로젝트에 대해 빌드 Configuration 설정을 "Test" 유형으로만 생성하기 때문에 이 상태에서는 "Build" 메뉴를 선택해도 rlib 파일을 생성하지 않습니다. <br /> <br /> 따라서 CLion의 "Terminal" 화면에서 "cargo build"를 입력해 빌드해야 하는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > PS F:\rust_prj\testapp2> <span style='color: blue; font-weight: bold'>cargo build</span> Compiling testapp2 v0.1.0 (F:\rust_prj\testapp2) Finished dev [unoptimized + debuginfo] target(s) in 0.27s </pre> <br /> 그럼, ./target/debug 디렉터리에 "libtestapp2.rlib" 파일이 생성됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 일단, 위와 같이 생성한 rlib 파일은 러스트 전용 라이브러리로써 Win32 DLL과는 다릅니다. 따라서 (C# 등에서 이용하려면) 출력을 Win32 DLL로 바꿔야 하는데요, 이를 위해 프로젝트에 추가된 Cargo.toml 파일에 crate-type 값을 다음과 같이 설정해 줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > [package] name = "testapp2" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html <span style='color: blue; font-weight: bold'>[lib] crate-type = ["cdylib"]</span> [dependencies] </pre> <br /> 이후, CLion의 "Edit Configurations"를 이용해 DLL로 빌드하는 모드를 하나 더 추가한 다음,<br /> <br /> <img onclick='toggle_img(this)' class='imgView' alt='rust_dll_prj_2.png' src='/SysWebRes/bbs/rust_dll_prj_2.png' /><br /> <br /> 다시 빌드하면 이제 ./target/debug 디렉터리에 testapp2.dll 파일이 생성됩니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 여기까지 하면, 비록 DLL은 생성되지만 add 함수가 외부로 노출된 상태는 아닙니다. Visual C++에서처럼 dllexport와 같은 처리를 해야 하는데요, 이를 위해 rust에서는 #[no_mangle]과 함께 extern 예약어를 적용해야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>#[no_mangle]</span> <span style='color: blue; font-weight: bold'>pub extern</span> fn add(left: usize, right: usize) -> usize { left + right } </pre> <br /> 이후 다시 빌드하고, dumpbin.exe를 이용해 DLL 정보를 확인하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > F:\rust_prj\testapp2\target\debug> <span style='color: blue; font-weight: bold'>dumpbin /EXPORTS testapp2.dll</span> ...[생략]... 00000000 characteristics FFFFFFFF time date stamp 0.00 version 1 ordinal base 1 number of functions 1 number of names ordinal hint RVA name <span style='color: blue; font-weight: bold'>1 0 00001000 add = add</span> ...[생략]... F:\rust_prj\testapp2\target\debug> <span style='color: blue; font-weight: bold'>dumpbin /HEADERS testapp2.dll</span> ...[생략]... FILE HEADER VALUES <span style='color: blue; font-weight: bold'>8664 machine (x64)</span> 5 number of sections 660B6574 time date stamp Tue Apr 2 10:55:00 2024 0 file pointer to symbol table 0 number of symbols F0 size of optional header 2022 characteristics Executable Application can handle large (>2GB) addresses DLL OPTIONAL HEADER VALUES 20B magic # (PE32+) ...[생략]... </pre> <br /> 일반적인 64bit PE32+ 포맷으로 add 함수를 export 시킨 것을 확인할 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> Rust 컴파일러가 출력한 결과물이 <a target='tab' href='https://www.sysnet.pe.kr/2/0/11139'>64비트 DLL이니까, calling convention 고민은 하지</a> 않아도 됩니다.<br /> <br /> 자, 그럼 C#에서 Rust DLL을 연결해 호출해 볼까요? ^^ 간단하게 Console 프로젝트를 하나 만들고, 이렇게 DllImport로 연결하면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System.Runtime.InteropServices; namespace ConsoleApp1; internal class Program { <span style='color: blue; font-weight: bold'>[DllImport("testapp2.dll")] static extern uint add(uint left, uint right);</span> static void Main(string[] args) { Console.WriteLine($"Hello, Rust!: {<span style='color: blue; font-weight: bold'>add(5, 6)</span>}"); } } </pre> <br /> 빌드 후 정상적으로 add 함수가 불리는 것을 확인할 수 있습니다. Rust 문법만 공부하면 심심할 테니, 이렇게 C#과 연동해 보면 좀 더 재미가 있을 것입니다. ^^<br /> <br /> 참고로, 관련해서 아래의 문서도 좀 보시고. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Creating A DLL With Rust ; <a target='tab' href='https://samrambles.com/guides/window-hacking-with-rust/creating-a-dll-with-rust/index.html'>https://samrambles.com/guides/window-hacking-with-rust/creating-a-dll-with-rust/index.html</a> rust-analyzer.vs ; <a target='tab' href='https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer'>https://marketplace.visualstudio.com/items?itemName=kitamstudios.RustAnalyzer</a> </pre> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1215
(왼쪽의 숫자를 입력해야 합니다.)