问题
I'm trying to call this native Windows method using JNA:
HRESULT WINAPI DirectSoundCreate(LPGUID lpGuid, LPDIRECTSOUND* ppDS, LPUNKNOWN pUnkOuter );
But I'm really struggling with understanding what I should use as parameters on the Java side of things. With JNA you're supposed to create Java classes matching the native C structs, and I have done so succesfully with other parts of the WinAPI.
From what I've (I think) understood so far the LPDIRECTSOUND is a typedef to a "Long pointer to a DirectSound struct" and LPUNKNOWN is a typedef "Long pointer to an Unknown"?
I've found the native structs IDirectSound and IUnknown in DSound.h. Am I supposed to use these? I can't find a specification on what these structs contain, however, so when I try to mirror them as empty classes extending Structure on the Java side I get
IllegalArgumentException: Structure class se.abjorklund.win32.jna.dsound.IDirectSound has unknown or zero size (ensure all fields are public)
So that obviously doesn't work. I'm guessing I'm missing something fundamental here, maybe it has something to do with the COM/Direct API that I don't understand, and answers like "go read up" are cool, as long as I can get pointers as to what to read!
Below is a working snippet of the C program I'm trying to port to Java using JNA.
LPDIRECTSOUND directSound;
if (directSoundCreate && SUCCEEDED(directSoundCreate(0, &directSound, 0)))
So in C you just pass a pointer to a LPDIRECTSOUND. I guess I need to make a LPDIRECTSOUND class extending the JNA Structure class in Java? Am I close to the answer here or way off?
回答1:
JNA does support COM and there are several mappings already present in the com.sun.jna.platform.win32.COM package, including the IUnknown
interface and the corresponding Unknown
class implementing it.
You could implement an IDirectSound
interface (optional) or just directly implement the class by extending Unknown
. You will have to map the functions you need using _invokeNativeObject() (or the -Int and -Void variants).
I contributed several COM classes needed to query WMI in the WbemCli.java class that can serve as examples of how to pass those parameters. (Note: I probably shouldn't have used the I
interface prefix on the concrete classes, but it's too late now.)
Function parameters are the vtableId, an array of objects for the arguments, and a class for the return type. To get the vtableId, you'll have to count the methods (0-indexed) in the directSoundVtbl
struct in the header file. I don't have a copy of the authoritative Dsound.h file, but here's one possibility for that ordering (e.g., CreateSoundBuffer
would have id 3). Inheriting from Unknown
already gets you the first 3 functions in the Vtbl (id's 0, 1, and 2).
Here's a (completely untested) example to get you started.
public interface DSound {
@FieldOrder ({ "dwSize", "dwFlags", ... })
class DSBUFFERDESC extends Structure {
public int dwSize;
public int dwFlags;
// continue conventional JNA Structure mapping here
// may have to map nested structures
}
class DirectSoundBuffer extends Unknown {
// methods invoking COM similar to below
}
class DirectSound extends Unknown {
public DirectSound() {
}
public DirectSound(Pointer p) {
super(p);
}
public HRESULT CreateSoundBuffer(DSBUFFERDESC lpcDSBufferDesc, DirectSoundBuffer lplpDirectSoundBuffer, Unknown pUnkOuter) {
// CreateSoundBuffer is 4th method of directSoundVtbl in Dsound.h
return (HRESULT) _invokeNativeObject(3,
new Object[] { getPointer(), lpcDSBufferDesc, lplpDirectSoundBuffer, pUnkOuter }, HRESULT.class);
}
// Map whatever functions you need, or all of them!
}
}
来源:https://stackoverflow.com/questions/61814337/is-it-possible-to-use-jna-jni-to-access-native-com-directx-api-methods