おはようございます。
これが私のシナリオです。私は、FooDevice と呼ばれる自動高速ペイバック デバイスと対話する、サード パーティの管理されていない foo.dll を持っています。私は foo.dll のメソッドのラッパーを作成し、それを FooWrapper と呼び、マーシャリングと少しのハンマーで最終的に機能させました。ご存知かもしれませんが、公開されてDllImport
いるすべてのメソッドを使用する場合は、としてマークする必要がありstatic
、extern
foo.dll はいくつかのメソッドとコールバック関数ポインターを公開します。異なるスレッドで 2 つのデバイスを同時に接続しようとすると、このコールバック関数をフックしようとするとラッパーがハングします。静的なものはスレッド共有であることを知っているので、AppDomain
FooWrapper インスタンスごとに異なるものを使用することを考えました。それがこの種の仕事をする正しい方法だと思いますか?
ここに私のFooWrapperのビット:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void FOO_EventHandlerFunc([In] UInt16 event_id, [In, Out] ref IntPtr data, [In] IntPtr param);
[SuppressUnmanagedCodeSecurity]
internal static class FOO
{
static FOO()
{
//...
}
///
/// FOO_RegisterEventHandler
/// The FOO_RegisterEventHandler function registers an application-defined callback
/// function, which will subsequently be called for all FooDevice generated events.
///
/// long FOO_RegisterEventHandler(FOO_EventHandlerFunc handler, BYTE evmask, LONG param);
///
/// Parameters
/// handler
/// [in] Pointer to an application-defined callback function (see below).
/// evmask
/// [in] Specify which events to enable (see EnableEvents).
/// param
/// [in] An application-defined value to be passed to the callback function
///
/// Return Values
/// If the function succeeds, the return value is zero.
/// If the function fails, the return value is nonzero.
///
/// Remarks
/// The FOO_EventHandlerFunc type defines a pointer to a callback function, which must
/// comply with the following, where FOO_EventHandlerFunc is a placeholder for the
/// application-defined function name.
///
/// void FOO_EventHandlerFunc(WORD event_id, LPVOID data, LONG param);
///
/// Parameters
/// event_id
/// [in] Event index as specified by the FooDevice protocol.
/// data
/// [in] Event data. The type of data depends on event_id.
/// (See the event specifications for FooDevice).
/// param
/// The application-defined value passed during registration.
///
/// Remarks
/// Avoid lengthy callback functions, since it will stall the underlying protocol,
/// thereby interrupting a steady communications flow.
/// FooDevice will only be generating events during operation.
/// That is - between FOO_LogIn and FOO_LogOut.
///
///The handler.
///The evmask.
///The param.
///
[DllImport("foo.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi)]
public static extern UInt32 FOO_RegisterEventHandler([In] [MarshalAs(UnmanagedType.FunctionPtr)] FOO_EventHandlerFunc handler, [In] byte evmask, [In] IntPtr param);
///
/// FOO_LogIn
/// The FOO_LogIn function opens FooDevice for normal operation.
///
/// long FOO_LogIn(LPSTR oper, LPSTR datetime);
///
/// Parameters
/// oper
/// [in] Pointer to a null-terminated string identifying the cashier.
/// The string can have any content, but a maximum of 50 characters will be used.
/// datetime
/// [in] Pointer to a null-terminated string indicating the current date and time.
/// The string must have 'YYYYMMDDhhmmss' format to take effect.
/// Return Values
/// If the function succeeds, the return value is zero.
/// If the function fails, the return value is nonzero.
///
///The oper.
///The datetime.
///
[DllImport("foo.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi)]
public static extern UInt32 FOO_LogIn([In] string oper, [In] string datetime);
//... and so on ...
}
}
FooWrapper を複数回 (同じスレッドまたは別のスレッドまたは AppDomain で) 正しくインスタンス化する方法を教えてください。
君たちありがとう。乾杯、ナンド