Win32 API 日本語リファレンス
ホーム › Storage.Xps › ExtEscape

ExtEscape

関数
デバイス固有の機能にアクセスするためプリンタなどへエスケープデータを送る。
DLLGDI32.dll呼出規約winapi対応OSWindows 2000 以降

シグネチャ

// GDI32.dll
#include <windows.h>

INT ExtEscape(
    HDC hdc,
    INT iEscape,
    INT cjInput,
    LPCSTR lpInData,   // optional
    INT cjOutput,
    LPSTR lpOutData   // optional
);

パラメーター

名前型方向説明
hdcHDCinデバイスコンテキストへのハンドル。
iEscapeINTin

実行するエスケープ関数。次のいずれか、またはアプリケーション定義のエスケープ関数を指定できます。

値 意味
CHECKJPEGFORMAT
プリンターが JPEG 画像をサポートしているかどうかを確認します。
CHECKPNGFORMAT
プリンターが PNG 画像をサポートしているかどうかを確認します。
DRAWPATTERNRECT
白、グレースケール、または黒の四角形を描画します。
GET_PS_FEATURESETTING
PostScript ドライバーの指定された機能設定に関する情報を取得します。
GETTECHNOLOGY
ドライバーが PostScript ドライバーであるかどうかを報告します。
PASSTHROUGH
アプリケーションがプリンターへ直接データを送信できるようにします。互換モードおよび GDI 中心モードでサポートされます。
POSTSCRIPT_DATA
アプリケーションがプリンターへ直接データを送信できるようにします。互換モードでのみサポートされます。
POSTSCRIPT_IDENTIFY
PostScript ドライバーを GDI 中心モードまたは PostScript 中心モードに設定します。
POSTSCRIPT_INJECTION
PostScript ジョブストリームに生データのブロックを挿入します。
POSTSCRIPT_PASSTHROUGH
PostScript プリンタードライバーへ直接データを送信します。互換モードおよび PostScript 中心モードでサポートされます。
QUERYESCSUPPORT
特定のエスケープがデバイスドライバーによって実装されているかどうかを判定します。
SPCLPASSTHROUGH2
ドキュメントレベルの save コンテキストで、アプリケーションがプライベートなプロシージャやその他のリソースを含められるようにします。
cjInputINTinlpszInData パラメーターが指すデータのバイト数。
lpInDataLPCSTRinoptional指定したエスケープに必要な入力構造体へのポインター。「解説」も参照してください。
cjOutputINTinlpszOutData パラメーターが指すデータのバイト数。
lpOutDataLPSTRoutoptionalこのエスケープからの出力を受け取る構造体へのポインター。ExtEscape をクエリ関数として呼び出す場合、このパラメーターを NULL にすることはできません。この構造体で返すデータがない場合は、cbOutput に 0 を設定します。「解説」も参照してください。

戻り値の型: INT

公式ドキュメント

ExtEscape 関数を使用すると、アプリケーションは GDI 経由では利用できないデバイスの機能にアクセスできます。

戻り値

戻り値は関数の結果を示します。関数が成功した場合は 0 より大きい値になります。ただし、実装の有無のみを確認する QUERYESCSUPPORT プリンターエスケープは例外です。エスケープが実装されていない場合、戻り値は 0 になります。0 未満の戻り値はエラーを示します。

解説(Remarks)

Note これはブロッキング関数 (同期関数) であり、すぐに制御が戻らない場合があります。この関数が戻るまでの速さは、ネットワークの状態、印刷サーバーの構成、プリンタードライバーの実装など、アプリケーションの作成時には予測しにくい実行時の要因に依存します。ユーザーインターフェイスとのやり取りを管理するスレッドからこの関数を呼び出すと、アプリケーションが応答していないように見えることがあります。
この関数は、ドライバー定義のエスケープ値をデバイスに渡すために使用します。

システム定義のエスケープ値をデバイスに渡すには、Escape 関数を使用してください。ただし、そのエスケープが nEscape に定義されたエスケープのいずれかである場合を除きます。ExtEscape は、システム定義のエスケープでは正しく動作しないことがあります。特に、lpszInData がポインターであるメンバーを含む構造体へのポインターであるようなエスケープは失敗します。

なお、この記事で説明する動作は期待される動作ですが、このモデルに従うかどうかはドライバー次第です。

lpszInData と lpszOutData が参照する変数は、同一であったり重なり合ったりしてはなりません。入力と出力のバッファーサイズ変数が重なっている場合、呼び出しから戻った後に正しい値が格納されていないことがあります。最良の結果を得るには、lpszInData と lpszOutData は別々の変数を参照するようにしてください。

CHECKJPEGFORMAT プリンターエスケープ関数は、プリンターが JPEG 画像の印刷をサポートしているかどうかを判定します。

CHECKJPEGFORMAT プリンターエスケープ関数を使用する前に、QUERYESCSUPPORT プリンターエスケープ関数を呼び出して、ドライバーが CHECKJPEGFORMAT をサポートしているかどうかを確認してください。CHECKJPEGFORMAT の使用方法を示すサンプルコードについては、プリンターの JPEG または PNG サポートのテストを参照してください。

CHECKPNGFORMAT プリンターエスケープ関数は、プリンターが PNG 画像の印刷をサポートしているかどうかを判定します。

CHECKJPEGFORMAT プリンターエスケープ関数を使用する前に、QUERYESCSUPPORT プリンターエスケープ関数を呼び出して、ドライバーが CHECKJPEGFORMAT をサポートしているかどうかを確認してください。サンプルコードについては、プリンターの JPEG または PNG サポートのテストを参照してください。

DRAWPATTERNRECT プリンターエスケープは、Hewlett-Packard LaserJet または LaserJet 互換プリンターにおける Page Control Language (PCL) のパターンおよびルール機能を使用して、白、グレースケール、または塗りつぶしの黒の四角形を作成します。グレースケールとは、黒と白のピクセルを特定の割合で混ぜたグレーのパターンです。

アプリケーションは、DRAWPATTERNRECT エスケープを使用する前に、QUERYESCSUPPORT エスケープを使用して、プリンターがパターンとルールを描画できるかどうかを確認する必要があります。

プリンターが白のルールをサポートしている場合は、それを使用して DRAWPATTERNRECT で作成したパターンを消去できます。プリンターが白のルールをサポートしていない場合、これらのパターンを消去する方法はありません。

アプリケーションが DRAWPATTERNRECT エスケープを使用できず、デバイスがプリンターである場合は、通常は代わりに PatBlt 関数を使用してください。PatBlt を使用して黒の四角形を印刷する場合は、BLACKNESS ラスターオペレーターを使用する必要がある点に注意してください。ただし、デバイスがプロッターの場合は、Rectangle 関数を使用してください。

GET_PS_FEATURESETTING プリンターエスケープ関数は、PostScript ドライバーの指定された機能設定に関する情報を取得します。

このエスケープ関数は、PostScript ドライバーが PostScript 中心モードまたは GDI 中心モードの場合にのみサポートされます。PostScript ドライバーのモードを設定するには、POSTSCRIPT_IDENTIFY エスケープ関数を呼び出します。

この操作を実行するには、次のパラメーターを指定して ExtEscape 関数を呼び出します。

GET_PS_FEATURESETTING プリンターエスケープ関数は、CreateDC 関数を呼び出した後、DeleteDC 関数を呼び出す前であれば、いつ呼び出しても有効です。

GETTECHNOLOGY プリンターエスケープ関数は、プリンタードライバーの種類を識別します。

XPSDrv 以外のプリンターの場合、このエスケープはドライバーが PostScript ドライバーであるかどうかを報告します。

XPSDrv プリンターの場合、このエスケープはドライバーが Microsoft XPS Document Converter (MXDC) であるかどうかを報告します。該当する場合、このエスケープはゼロ終端文字列 "http://schemas.microsoft.com/xps/2005/06" を返します

PASSTHROUGH プリンターエスケープ関数は、プリンタードライバーへ直接データを送信します。この操作を実行するには、次のパラメーターを指定して ExtEscape 関数を呼び出します。

PASSTHROUGH プリンターエスケープ関数は、GDI 中心モードまたは互換モードの PostScript ドライバーでサポートされますが、PostScript 中心モードではサポートされません。PostScript 中心モードのドライバーでは、POSTSCRIPT_PASSTHROUGH エスケープ関数を使用できます。PostScript ドライバーのモードを設定するには、POSTSCRIPT_IDENTIFY エスケープ関数を呼び出します。

EPSPRINTING または PostScript 中心のアプリケーションから送信された PASSTHROUGH データに対しては、PostScript ドライバーは一切変更を加えません。それ以外のアプリケーションから送信された PASSTHROUGH データについては、PostScript ドライバーが BCP (Binary Communication Protocol) または TBCP (Tagged Binary Communication Protocol) の出力プロトコルを使用している場合、ドライバーは「Adobe Serial and Parallel Communications Protocols Specification」に記載されているとおり、特殊文字に対して適切な BCP または TBCP のクォート処理を行います。したがって、アプリケーションは ASCII または純粋なバイナリのいずれかの PASSTHROUGH データを送信する必要があります。

POSTSCRIPT_DATA プリンターエスケープ関数は、プリンタードライバーへ直接データを送信します。この操作を実行するには、次のパラメーターを指定して ExtEscape 関数を呼び出します。

POSTSCRIPT_DATA 関数は PASSTHROUGH エスケープ関数と同一ですが、互換モードの PostScript ドライバーでのみサポートされる点が異なります。PostScript 中心モードまたは GDI 中心モードの PostScript ドライバーではサポートされません。

PostScript 中心モードのドライバーでは POSTSCRIPT_PASSTHROUGH エスケープ関数を、GDI 中心モードのドライバーでは PASSTHROUGH エスケープ関数を使用できます。PostScript ドライバーのモードを設定するには、POSTSCRIPT_IDENTIFY エスケープ関数を呼び出します。

POSTSCRIPT_IDENTIFY プリンターエスケープ関数は、PostScript ドライバーを GDI 中心モードまたは PostScript 中心モードに設定します。

ドライバーを GDI 中心モードまたは PostScript 中心モードにするには、まず QUERYESCSUPPORT プリンターエスケープ関数を呼び出して、ドライバーが POSTSCRIPT_IDENTIFY プリンターエスケープ関数をサポートしているかどうかを確認します。サポートしている場合、そのドライバーは PSCRIPT 5.0 であると見なせます。その後、他のプリンターエスケープ関数を呼び出す前に、POSTSCRIPT_IDENTIFY を呼び出して PSIDENT_GDICENTRIC または PSIDENT_PSCENTRIC のいずれかを指定する必要があります。QUERYESCSUPPORT と POSTSCRIPT_IDENTIFY の各プリンターエスケープ関数は、他のプリンターエスケープ関数を呼び出す前に呼び出す必要があります。

Note PostScript ドライバーを GDI 中心モードまたは PostScript 中心モードに設定した後は、POSTSCRIPT_IDENTIFY プリンターエスケープ関数を呼び出すことはできなくなります。
POSTSCRIPT_IDENTIFY プリンターエスケープ関数を使用しない場合、PostScript ドライバーは互換モードとなり、PASSTHROUGH、POSTSCRIPT_PASSTHROUGH、POSTSCRIPT_DATA の各プリンターエスケープ関数を同等にサポートします。

POSTSCRIPT_PASSTHROUGH をサポートする PostScript ドライバーでは、PASSTHROUGH と POSTSCRIPT_PASSTHROUGH のプリンターエスケープ関数は同一です。

PostScript 中心モードでは、用紙にマークを付けるすべての PostScript 出力を、POSTSCRIPT_PASSTHROUGH エスケープ関数を使用してアプリケーションが行う責任を負います。GDI 関数は使用できません。ドキュメント全体の構造とプリンターの制御設定はドライバーが担当します。アプリケーションは、POSTSCRIPT_INJECTION プリンターエスケープ関数を使用して、ジョブストリームの特定の位置に生データのブロック (DSC コメントを含む) を挿入できます。

POSTSCRIPT_INJECTION プリンターエスケープ関数は、PostScript ジョブストリームの指定された位置に生データのブロックを挿入します。

PostScript ドライバーは、GDI 中心モードまたは PostScript 中心モードではこのエスケープ関数をサポートしますが、互換モードではサポートしません。

PostScript ドライバーのモードを設定するには、POSTSCRIPT_IDENTIFY エスケープ関数を呼び出します。

この操作を実行するには、次のパラメーターを指定して ExtEscape 関数を呼び出します。

ドライバーは挿入データを内部的にキャッシュし、出力の適切な位置でそれを出力します。キャッシュされた情報は、不要になった時点で破棄されます。遅くとも EndDoc の呼び出し後には破棄されます。

GDI 中心モードでは、アプリケーションは POSTSCRIPT_INJECTION プリンターエスケープ関数を使用して、有効な DSC ブロックデータのみを挿入できます。有効な DSC ブロックは、次の条件をすべて満たす必要があります。

POSTSCRIPT_PASSTHROUGH プリンターエスケープ関数は、PostScript プリンタードライバーへ直接データを送信します。

PostScript ドライバーは、PostScript 中心モードまたは互換モードではこのエスケープ関数をサポートしますが、GDI 中心モードではサポートしません。

PostScript ドライバーのモードを設定するには、POSTSCRIPT_IDENTIFY エスケープ関数を呼び出します。

QUERYESCSUPPORT プリンターエスケープ関数は、プリンターエスケープ関数が実装されているかどうかを確認します。

SPCLPASSTHROUGH2 プリンターエスケープ関数は、EPSPRINTING を使用して PostScript デバイスに印刷するアプリケーションが、ドキュメントレベルの save コンテキストでプライベートな PostScript プロシージャやその他のリソースを含められるようにします。

このエスケープは、Adobe Acrobat との下位互換性のためにのみサポートされています。他のアプリケーションでは、この廃止されたエスケープを使用しないでください。

アプリケーションは、ドライバーが PostScript ストリームの正しい位置に挿入できるようデータをキャッシュするために、StartDoc を呼び出す前にこのエスケープを呼び出す必要があります。このエスケープがサポートされている場合、ドライバーは StartDoc より前の DOWNLOADFACE エスケープの呼び出しも許可します。ドライバーは、挿入するデータと、StartDoc より前の DOWNLOADFACE エスケープ呼び出しに必要なデータを内部的にキャッシュし、%%EndProlog の直前にそれらをすべて出力します。SPCLPASSTHROUGH2 と DOWNLOADFACE の呼び出しの順序は、データが渡された順序どおりに保持されます。つまり、後の呼び出しのデータは、先の呼び出しのデータより後に出力されます。ドライバーは、StartDoc より前の DOWNLOADFACE エスケープ呼び出しによってダウンロードされたフォントを、そのジョブの範囲内では削除できないものとして扱います。

このエスケープはオペレーティングシステムによって EMF ファイルに記録されません。そのため、アプリケーションはこのエスケープを使用するジョブについて EMF の記録が無効になっていることを確認する必要があります。

例

例については、JPEG または PNG 画像のサイズ設定を参照してください。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// GDI32.dll
#include <windows.h>

INT ExtEscape(
    HDC hdc,
    INT iEscape,
    INT cjInput,
    LPCSTR lpInData,   // optional
    INT cjOutput,
    LPSTR lpOutData   // optional
);
[DllImport("GDI32.dll", ExactSpelling = true)]
static extern int ExtEscape(
    IntPtr hdc,   // HDC
    int iEscape,   // INT
    int cjInput,   // INT
    [MarshalAs(UnmanagedType.LPStr)] string lpInData,   // LPCSTR optional
    int cjOutput,   // INT
    [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder lpOutData   // LPSTR optional, out
);
<DllImport("GDI32.dll", ExactSpelling:=True)>
Public Shared Function ExtEscape(
    hdc As IntPtr,   ' HDC
    iEscape As Integer,   ' INT
    cjInput As Integer,   ' INT
    <MarshalAs(UnmanagedType.LPStr)> lpInData As String,   ' LPCSTR optional
    cjOutput As Integer,   ' INT
    <MarshalAs(UnmanagedType.LPStr)> lpOutData As System.Text.StringBuilder   ' LPSTR optional, out
) As Integer
End Function
' hdc : HDC
' iEscape : INT
' cjInput : INT
' lpInData : LPCSTR optional
' cjOutput : INT
' lpOutData : LPSTR optional, out
Declare PtrSafe Function ExtEscape Lib "gdi32" ( _
    ByVal hdc As LongPtr, _
    ByVal iEscape As Long, _
    ByVal cjInput As Long, _
    ByVal lpInData As String, _
    ByVal cjOutput As Long, _
    ByVal lpOutData As String) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

ExtEscape = ctypes.windll.gdi32.ExtEscape
ExtEscape.restype = ctypes.c_int
ExtEscape.argtypes = [
    wintypes.HANDLE,  # hdc : HDC
    ctypes.c_int,  # iEscape : INT
    ctypes.c_int,  # cjInput : INT
    wintypes.LPCSTR,  # lpInData : LPCSTR optional
    ctypes.c_int,  # cjOutput : INT
    wintypes.LPSTR,  # lpOutData : LPSTR optional, out
]
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('GDI32.dll')
ExtEscape = Fiddle::Function.new(
  lib['ExtEscape'],
  [
    Fiddle::TYPE_VOIDP,  # hdc : HDC
    Fiddle::TYPE_INT,  # iEscape : INT
    Fiddle::TYPE_INT,  # cjInput : INT
    Fiddle::TYPE_VOIDP,  # lpInData : LPCSTR optional
    Fiddle::TYPE_INT,  # cjOutput : INT
    Fiddle::TYPE_VOIDP,  # lpOutData : LPSTR optional, out
  ],
  Fiddle::TYPE_INT)
#[link(name = "gdi32")]
extern "system" {
    fn ExtEscape(
        hdc: *mut core::ffi::c_void,  // HDC
        iEscape: i32,  // INT
        cjInput: i32,  // INT
        lpInData: *const u8,  // LPCSTR optional
        cjOutput: i32,  // INT
        lpOutData: *mut u8  // LPSTR optional, out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("GDI32.dll")]
public static extern int ExtEscape(IntPtr hdc, int iEscape, int cjInput, [MarshalAs(UnmanagedType.LPStr)] string lpInData, int cjOutput, [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder lpOutData);
"@
$api = Add-Type -MemberDefinition $sig -Name 'GDI32_ExtEscape' -Namespace Win32 -PassThru
# $api::ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
#uselib "GDI32.dll"
#func global ExtEscape "ExtEscape" sptr, sptr, sptr, sptr, sptr, sptr
; ExtEscape hdc, iEscape, cjInput, lpInData, cjOutput, varptr(lpOutData)   ; 戻り値は stat
; hdc : HDC -> "sptr"
; iEscape : INT -> "sptr"
; cjInput : INT -> "sptr"
; lpInData : LPCSTR optional -> "sptr"
; cjOutput : INT -> "sptr"
; lpOutData : LPSTR optional, out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "GDI32.dll"
#cfunc global ExtEscape "ExtEscape" sptr, int, int, str, int, var
; res = ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
; hdc : HDC -> "sptr"
; iEscape : INT -> "int"
; cjInput : INT -> "int"
; lpInData : LPCSTR optional -> "str"
; cjOutput : INT -> "int"
; lpOutData : LPSTR optional, out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT ExtEscape(HDC hdc, INT iEscape, INT cjInput, LPCSTR lpInData, INT cjOutput, LPSTR lpOutData)
#uselib "GDI32.dll"
#cfunc global ExtEscape "ExtEscape" intptr, int, int, str, int, var
; res = ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
; hdc : HDC -> "intptr"
; iEscape : INT -> "int"
; cjInput : INT -> "int"
; lpInData : LPCSTR optional -> "str"
; cjOutput : INT -> "int"
; lpOutData : LPSTR optional, out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	gdi32 = windows.NewLazySystemDLL("GDI32.dll")
	procExtEscape = gdi32.NewProc("ExtEscape")
)

// hdc (HDC), iEscape (INT), cjInput (INT), lpInData (LPCSTR optional), cjOutput (INT), lpOutData (LPSTR optional, out)
r1, _, err := procExtEscape.Call(
	uintptr(hdc),
	uintptr(iEscape),
	uintptr(cjInput),
	uintptr(unsafe.Pointer(windows.BytePtrFromString(lpInData))),
	uintptr(cjOutput),
	uintptr(lpOutData),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function ExtEscape(
  hdc: THandle;   // HDC
  iEscape: Integer;   // INT
  cjInput: Integer;   // INT
  lpInData: PAnsiChar;   // LPCSTR optional
  cjOutput: Integer;   // INT
  lpOutData: PAnsiChar   // LPSTR optional, out
): Integer; stdcall;
  external 'GDI32.dll' name 'ExtEscape';
result := DllCall("GDI32\ExtEscape"
    , "Ptr", hdc   ; HDC
    , "Int", iEscape   ; INT
    , "Int", cjInput   ; INT
    , "AStr", lpInData   ; LPCSTR optional
    , "Int", cjOutput   ; INT
    , "Ptr", lpOutData   ; LPSTR optional, out
    , "Int")   ; return: INT
●ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData) = DLL("GDI32.dll", "int ExtEscape(void*, int, int, char*, int, char*)")
# 呼び出し: ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
# hdc : HDC -> "void*"
# iEscape : INT -> "int"
# cjInput : INT -> "int"
# lpInData : LPCSTR optional -> "char*"
# cjOutput : INT -> "int"
# lpOutData : LPSTR optional, out -> "char*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "gdi32" fn ExtEscape(
    hdc: ?*anyopaque, // HDC
    iEscape: i32, // INT
    cjInput: i32, // INT
    lpInData: [*c]const u8, // LPCSTR optional
    cjOutput: i32, // INT
    lpOutData: [*c]u8 // LPSTR optional, out
) callconv(std.os.windows.WINAPI) i32;
proc ExtEscape(
    hdc: pointer,  # HDC
    iEscape: int32,  # INT
    cjInput: int32,  # INT
    lpInData: cstring,  # LPCSTR optional
    cjOutput: int32,  # INT
    lpOutData: ptr char  # LPSTR optional, out
): int32 {.importc: "ExtEscape", stdcall, dynlib: "GDI32.dll".}
pragma(lib, "gdi32");
extern(Windows)
int ExtEscape(
    void* hdc,   // HDC
    int iEscape,   // INT
    int cjInput,   // INT
    const(char)* lpInData,   // LPCSTR optional
    int cjOutput,   // INT
    char* lpOutData   // LPSTR optional, out
);
ccall((:ExtEscape, "GDI32.dll"), stdcall, Int32,
      (Ptr{Cvoid}, Int32, Int32, Cstring, Int32, Ptr{UInt8}),
      hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
# hdc : HDC -> Ptr{Cvoid}
# iEscape : INT -> Int32
# cjInput : INT -> Int32
# lpInData : LPCSTR optional -> Cstring
# cjOutput : INT -> Int32
# lpOutData : LPSTR optional, out -> Ptr{UInt8}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t ExtEscape(
    void* hdc,
    int32_t iEscape,
    int32_t cjInput,
    const char* lpInData,
    int32_t cjOutput,
    char* lpOutData);
]]
local gdi32 = ffi.load("gdi32")
-- gdi32.ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
-- hdc : HDC
-- iEscape : INT
-- cjInput : INT
-- lpInData : LPCSTR optional
-- cjOutput : INT
-- lpOutData : LPSTR optional, out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('GDI32.dll');
const ExtEscape = lib.func('__stdcall', 'ExtEscape', 'int32_t', ['void *', 'int32_t', 'int32_t', 'str', 'int32_t', 'char *']);
// ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
// hdc : HDC -> 'void *'
// iEscape : INT -> 'int32_t'
// cjInput : INT -> 'int32_t'
// lpInData : LPCSTR optional -> 'str'
// cjOutput : INT -> 'int32_t'
// lpOutData : LPSTR optional, out -> 'char *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("GDI32.dll", {
  ExtEscape: { parameters: ["pointer", "i32", "i32", "buffer", "i32", "buffer"], result: "i32" },
});
// lib.symbols.ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData)
// hdc : HDC -> "pointer"
// iEscape : INT -> "i32"
// cjInput : INT -> "i32"
// lpInData : LPCSTR optional -> "buffer"
// cjOutput : INT -> "i32"
// lpOutData : LPSTR optional, out -> "buffer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t ExtEscape(
    void* hdc,
    int32_t iEscape,
    int32_t cjInput,
    const char* lpInData,
    int32_t cjOutput,
    char* lpOutData);
C, "GDI32.dll");
// $ffi->ExtEscape(hdc, iEscape, cjInput, lpInData, cjOutput, lpOutData);
// hdc : HDC
// iEscape : INT
// cjInput : INT
// lpInData : LPCSTR optional
// cjOutput : INT
// lpOutData : LPSTR optional, out
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。
import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Gdi32 extends StdCallLibrary {
    Gdi32 INSTANCE = Native.load("gdi32", Gdi32.class);
    int ExtEscape(
        Pointer hdc,   // HDC
        int iEscape,   // INT
        int cjInput,   // INT
        String lpInData,   // LPCSTR optional
        int cjOutput,   // INT
        byte[] lpOutData   // LPSTR optional, out
    );
}
@[Link("gdi32")]
lib LibGDI32
  fun ExtEscape = ExtEscape(
    hdc : Void*,   # HDC
    iEscape : Int32,   # INT
    cjInput : Int32,   # INT
    lpInData : UInt8*,   # LPCSTR optional
    cjOutput : Int32,   # INT
    lpOutData : UInt8*   # LPSTR optional, out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef ExtEscapeNative = Int32 Function(Pointer<Void>, Int32, Int32, Pointer<Utf8>, Int32, Pointer<Utf8>);
typedef ExtEscapeDart = int Function(Pointer<Void>, int, int, Pointer<Utf8>, int, Pointer<Utf8>);
final ExtEscape = DynamicLibrary.open('GDI32.dll')
    .lookupFunction<ExtEscapeNative, ExtEscapeDart>('ExtEscape');
// hdc : HDC -> Pointer<Void>
// iEscape : INT -> Int32
// cjInput : INT -> Int32
// lpInData : LPCSTR optional -> Pointer<Utf8>
// cjOutput : INT -> Int32
// lpOutData : LPSTR optional, out -> Pointer<Utf8>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function ExtEscape(
  hdc: THandle;   // HDC
  iEscape: Integer;   // INT
  cjInput: Integer;   // INT
  lpInData: PAnsiChar;   // LPCSTR optional
  cjOutput: Integer;   // INT
  lpOutData: PAnsiChar   // LPSTR optional, out
): Integer; stdcall;
  external 'GDI32.dll' name 'ExtEscape';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "ExtEscape"
  c_ExtEscape :: Ptr () -> Int32 -> Int32 -> CString -> Int32 -> CString -> IO Int32
-- hdc : HDC -> Ptr ()
-- iEscape : INT -> Int32
-- cjInput : INT -> Int32
-- lpInData : LPCSTR optional -> CString
-- cjOutput : INT -> Int32
-- lpOutData : LPSTR optional, out -> CString
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let extescape =
  foreign "ExtEscape"
    ((ptr void) @-> int32_t @-> int32_t @-> string @-> int32_t @-> string @-> returning int32_t)
(* hdc : HDC -> (ptr void) *)
(* iEscape : INT -> int32_t *)
(* cjInput : INT -> int32_t *)
(* lpInData : LPCSTR optional -> string *)
(* cjOutput : INT -> int32_t *)
(* lpOutData : LPSTR optional, out -> string *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)
(cffi:define-foreign-library gdi32 (t "GDI32.dll"))
(cffi:use-foreign-library gdi32)

(cffi:defcfun ("ExtEscape" ext-escape :convention :stdcall) :int32
  (hdc :pointer)   ; HDC
  (i-escape :int32)   ; INT
  (cj-input :int32)   ; INT
  (lp-in-data :string)   ; LPCSTR optional
  (cj-output :int32)   ; INT
  (lp-out-data :pointer))   ; LPSTR optional, out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $ExtEscape = Win32::API::More->new('GDI32',
    'int ExtEscape(HANDLE hdc, int iEscape, int cjInput, LPCSTR lpInData, int cjOutput, LPSTR lpOutData)');
# my $ret = $ExtEscape->Call($hdc, $iEscape, $cjInput, $lpInData, $cjOutput, $lpOutData);
# hdc : HDC -> HANDLE
# iEscape : INT -> int
# cjInput : INT -> int
# lpInData : LPCSTR optional -> LPCSTR
# cjOutput : INT -> int
# lpOutData : LPSTR optional, out -> LPSTR
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目