トップ «前の日記(2008-11-23) 最新 次の日記(2008-11-25)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2008-11-24

_ 逆P/Invoke

MSKBの「DLLとは」というINFOは、シンプルな題名と裏腹になかなか楽しいことが書いてある。

が、いかんせん、中途半端で、しかもちょっと古いかも知れない。

試してみたが、clr2.5では、vtfixupについての修正は不要なようだ(メソッドシグネチャによるのかも知れないけど)。さらに.corflagsの修正も必要ない。

// MyAssembly.cs
using System;
public static class MyAsm
{
    public static void HelloWorld()
    {
        Console.WriteLine("Hello World!");    
    }   
    public static void HelloMyWorld(int count)
    {
        for (int i = 0; i < count; i++)
            Console.WriteLine("Hello My World!");    
    }
}
これを
c:\temp>csc /target:library MyAssembly.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.
でもって
c:\temp>ildasm /out:MyAssembly.il MyAssembly.dll
さらに
c:\home\arton\temp>diff -u -2 MyAssembly.il~ MyAssembly.il
--- MyAssembly.il~      Mon Nov 24 03:06:28 2008
+++ MyAssembly.il       Mon Nov 24 03:07:27 2008
@@ -36,4 +36,5 @@
   .method public hidebysig static void  HelloWorld() cil managed
   {
+    .export [1]
     // コード サイズ       13 (0xd)
     .maxstack  8
@@ -47,4 +48,5 @@
   .method public hidebysig static void  HelloMyWorld(int32 count) cil managed
   {
+    .export [2]
     // コード サイズ       29 (0x1d)
     .maxstack  2
としてから
c:\temp>ilasm /dll MyAssembly.il
 
Microsoft (R) .NET Framework IL Assembler.  Version 2.0.50727.3053
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'MyAssembly.il'  to DLL --> 'MyAssembly.dll'
Source file is ANSI
 
Assembled method MyAsm::HelloWorld
Assembled method MyAsm::HelloMyWorld
Creating PE file
 
Emitting classes:
Class 1:        MyAsm
 
Emitting fields and methods:
Global
Class 1 Methods: 2;
 
Emitting events and properties:
Global
Class 1
Writing PE file
Operation completed successfully
で、dllができたので、一応corflagsを見てみる。
c:\temp>corflags MyAssembly.dll
Microsoft (R) .NET Framework CorFlags Conversion Tool.  Version  3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.
 
Version   : v2.0.50727
CLR Header: 2.5
PE        : PE32
CorFlags  : 2
ILONLY    : 0
32BIT     : 1
Signed    : 0
というわけで、ILONLYは自動的に落とされていて問題なさそうなので、まずはCで逆P/Invoke(これがそうかはちょっと疑問)。
// impasm.c
#include <windows.h>
int main(int argc, char* argv[])
{
    HMODULE h = LoadLibrary("MyAssembly.dll");
    FARPROC fnc = GetProcAddress(h, "HelloWorld");
    fnc();
    fnc = GetProcAddress(h, "HelloMyWorld");
    ((void (*)(int))fnc)(2);
    return 0;
}
コンパイルして実行。
c:\temp>cl impasm.c
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.
 
impasm.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.
 
/out:impasm.exe
impasm.obj
 
c:\temp>impasm
Hello World!
Hello My World!
Hello My World!
しかし、引数がintでstaticメンバ関数の呼び出しだからちょろいわけだが、オブジェクトを使いたかったり、文字列を使うには、やはり^とかが必要になると思うわけで、それほど嬉しくないかも。
でも、static void(*)(void)なラッパ関数を作ってやれば、Cから呼べるのだから、それなりに楽しいかな。たとえばRuby拡張ライブラリとかだったらどうか?
本日のツッコミ(全1件) [ツッコミを入れる]
_ ARAI (2008-11-24 07:43)

いやー、有難うございます。<br>coflagsが落ちるのは、気がついて無かった。MSDNライブラリによれば、Managed C++のリンカでもできるらしいです(こっちは未確認)。<br>ラウンド・トリップ(C#-IL)は出来ないけど、C/C++に詳しくない人には便利かもと思っていたりします。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|

ジェズイットを見習え