Posted on 2025/06/01, 8:32 AM By admin22
本来、Windowsの.Net Framework で行われている、interoperability(相互運用性)のテストをmacOSで試してみました。
アンマネージド ライブラリ内の構造体、コールバック、および関数をマネージド コードからアクセスできるようにするP/Invoke(プラットフォーム呼び出し)を使います。
参考)
https://learn.microsoft.com/ja-jp/dotnet/standard/native-interop/pinvoke
コンソールアプリケーションのプロジェクト作成
dotnet new console -n interop
上記サイトのサンプルから、アンマネージライブラリを使ってプロセスIDの取得とディレクトリ情報の取得をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
using System; using System.Runtime.InteropServices; namespace PInvokeSamples { public static partial class Program { // Define a delegate that has the same signature as the native function. private delegate int DirClbk(string fName, ref Stat stat, int typeFlag); // Import the libSystem shared library and define the method // corresponding to the native function. [LibraryImport("libSystem.dylib")] private static partial int getpid(); // Import the libc and define the method to represent the native function. [LibraryImport("libSystem.dylib", StringMarshalling = StringMarshalling.Utf16)] private static partial int ftw(string dirpath, DirClbk cl, int descriptors); // Implement the above DirClbk delegate; // this one just prints out the filename that is passed to it. private static int DisplayEntry(string fName, ref Stat stat, int typeFlag) { Console.WriteLine("{0} / {1}", fName, stat.UserID); return 0; } public static void Main(string[] args) { // Invoke the function and get the process ID. int pid = getpid(); Console.WriteLine(pid); // Call the native function. // Note the second parameter which represents the delegate (callback). ftw(".", DisplayEntry, 10); } } // The native callback takes a pointer to a struct. This type // represents that struct in managed code. [StructLayout(LayoutKind.Sequential)] public struct Stat { public uint DeviceID; public uint InodeNumber; public uint Mode; public uint HardLinks; public uint UserID; public uint GroupID; public uint SpecialDeviceID; public ulong Size; public ulong BlockSize; public uint Blocks; public long TimeLastAccess; public long TimeLastModification; public long TimeLastStatusChange; } } |
実行
dotnet run
以下はディレクトリ情報取得の動作確認用のCプログラムです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#define _XOPEN_SOURCE 500 // ftwのために必要 #include <ftw.h> #include <stdio.h> #include <stdlib.h> // コールバック関数: ファイルごとに呼ばれる int list(const char *fpath, const struct stat *sb, int typeflag) { printf("%s %u %lld\n", fpath, sb->st_uid, sb->st_size); return 0; // 0を返すと続行、非0を返すと中断 } int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s <directory_path>\n", argv[0]); exit(EXIT_FAILURE); } // ftw関数でディレクトリを再帰的に探索 if (ftw(argv[1], list, 16) == -1) { perror("ftw"); exit(EXIT_FAILURE); } return 0; } |
ビルド、実行
gcc -o ftw_sample ftw_sample.c
./ftw_sample .
InvokeSampleのstruct Statの定義が不正確のため、実際とはアライメントがずれてしまっていました。
前回に続き、.Net/Mac でした。
Categories: 未分類