hishidaの開発blog

EBシリーズ(EBPocket,EBWin,EBMac,EBStudio),KWIC Finder,xdoc2txt,読書尚友の開発者ブログ

【重要】xdoc2txt DLL版の関数呼び出し規約について

Windowsでは関数の呼び出し規約にcdeclとstdcallがあり、C言語の呼び出しではcdecl、その他の言語ではstdcallが標準になっています。スタックの解放を呼び出し側が行うか、呼ばれる側が行うかの違いです。呼び出し規約が呼び出し側と呼ばれる側で違っている場合、スタックが不安定になる可能性があります。
xdoc2txtのDLLの呼び出し規約はcdeclですが、DLLを呼び出すサンプルプログラムの記述がこれまでstdcallになっていたことが判明しました。xdoc2txtのDLLを呼び出すプログラムを作成されているベンダの方は、大変申し訳ありませんが、cdeclで呼ぶように修正していただければ幸いです。

呼び出し方法はver2.08のサンプルプログラムとREADMEをご参照ください。下記の赤線部分が追加です。
xdoc2txt

C#の例(1):DllImport版

[DllImport("xd2txlib.dll", CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Cdecl)]
public static extern int ExtractText(
[MarshalAs(UnmanagedType.BStr)] String lpFileName,
bool bProp,
[MarshalAs(UnmanagedType.BStr)] ref String lpFileText);

string fileName = "sample.doc";
string fileText = "";
int fileLength = ExtractText( fileName, false, ref fileText );

C#の例(2):動的ロード版

// LoadLibrary、FreeLibrary、GetProcAddressをインポート
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", SetLastError = true)]
internal static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = false)]
internal static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

// 関数をdelegateで宣言する
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int ExtractText(
[MarshalAs(UnmanagedType.BStr)] String lpFileName,
bool bProp,
[MarshalAs(UnmanagedType.BStr)] ref String lpFileText);

string fileName = "sample.doc";
string fileText = "";
// 動的にdllをロードし、使用後に解放
IntPtr handle = LoadLibrary("xd2txlib.dll");
IntPtr funcPtr = GetProcAddress(handle, "ExtractText");

ExtractText extractText = (ExtractText)Marshal.GetDelegateForFunctionPointer(funcPtr, typeof(ExtractText));
int fileLength = extractText(fileName, false, ref fileText);
FreeLibrary(handle);