質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

3回答

681閲覧

【Rust】winapiの関数のアドレスを取得する方法ってありますか

KOTTON

総合スコア47

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2021/09/29 02:07

質問

C++のコードの以下をRust(winapi)で表したいです。

cpp

1#include <Windows.h> 2#include <iostream> 3std::cout << (void*)CreateFileW << std::endl;

試したこと

rust

1use winapi::shared::minwindef::LPVOID; 2use winapi::um::fileapi::CreateFileW; 3println!("{:?}", CreateFileW as LPVOID); 4println!("{:?}", CreateFileW as *const ());

同じプロセス上でC++とRustのコードを実行して試したのですが、このどちらもがC++と同じ結果になりませんでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

rust

1println!("{:?}", CreateFileW as LPVOID); 2println!("{:?}", CreateFileW as *const ())

試してませんが、上のやり方で合っていると思います。なおフォーマットとして{:p}を使うと、わざわざ別の型に変換しないでアドレスが表示できるはずです。

rust

1println!("{:p}", CreateFileW);

同じプロセス上でC++とRustのコードを実行して試したのですが、このどちらもがC++と同じ結果になりませんでした。

まず、Rustのwinapiクレート上のCreateFileW関数の定義を確認したところ、以下のようになっていました。extern指定を使うことでWindows APIライブラリーの素の関数を直接使用しています。

rust

1pub unsafe extern "system" fn CreateFileW( 2 lpFileName: LPCWSTR, 3 dwDesiredAccess: DWORD, 4 dwShareMode: DWORD, 5 lpSecurityAttributes: LPSECURITY_ATTRIBUTES, 6 dwCreationDisposition: DWORD, 7 dwFlagsAndAttributes: DWORD, 8 hTemplateFile: HANDLE 9) -> HANDLE

winapiクレートはドキュメントがほとんどないのでよくわからないのですが、恐らくC++プログラムから動的リンクされているWindows APIとは違うものを使っているようです。デフォルトではRustプログラムをwinapiクレートにバンドル(同梱)されているWindows APIのライブラリーと静的リンクするようです。

winapiクレートビルドスクリプト

winapiクレートにバンドルされているライブラリー

RustとC++で別のライブラリーにリンクされているので、異なったアドレスが表示されるのではないでしょうか?

投稿2021/09/29 03:12

編集2021/09/29 03:57
tatsuya6502

総合スコア2046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOTTON

2021/09/29 09:45

回答ありがとうございます!!!! いとも簡単にクレートのリポジトリの内部を探索されていて本当に感服しました > 上のやり方で合っていると思います。 一応このやり方は間違ってないということで安心しました。 結局のところ、GetProcAddress(hModule, functionName) を使うだけで関数のポインタが得られるということが分かりました。理由は分かりませんがこれはC++と同じ結果が返ってきました。完全にこの関数のことを失念しておりました。 いつもお忙しい中回答していただいてありがとうございます!!!!!!m(_ _)m
tatsuya6502

2021/09/29 10:43 編集

自己解決されたということでよかったです! もし私の言っている、Rust側はWindows APIが静的リンクしている? が正しいとすると、 ・静的リンクされた方のライブラリーにあるGetProcAddress関数を使って ・動的リンクされたKERNEL32.dllにあるCreateFileW関数のアドレスを取得している ということになるのかな? ちょっとスッキリしませんが、目的は達成できたようですのでよかったです。
guest

0

自己解決

回答いただいたお二方には大変申し訳ないのですが、一応僕の方で解決しましたので、自己解決という形をとらせていただきます!(ですがためになる回答ありがとうございました。

GetProcAddressを使うことでアドレスを得ることができました。
パラメータの文字列は、Null terminatorを付けたうえで*i8に変換する必要があります。

rs

1GetProcAddress(GetModuleHandleA("KERNEL32.dll\0".as_ptr() as *const i8), "CreateFileW\0".as_ptr() as *const i8)

投稿2021/09/29 09:52

KOTTON

総合スコア47

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

WindowsのAPIってのは、DLLファイルをメモリ上にロードしてきて目的の関数を実行するって形になってます。
そのうえ、関数の呼び出し形式ってのは言語ごとに違うんで、それをAPIの関数の形式に変換する必要があるため、大抵は同名の関数を定義して、引数やら呼び出し形式やら加工してから素のAPIを呼び出すようになってます

ということで、常に同じメモリエリアに常駐してるってもんでもないです。

投稿2021/09/29 02:55

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KOTTON

2021/09/29 09:48

回答ありがとうございます!! なるほどそのような仕組みになっているのですね 私はこのあたりのことを抽象的にしか理解していないためとても助かります
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問