Hello,
I'm trying to invoke methods on a COM object that was passed to me by a VB application. It works fine when methods are called from inside the Java COM server method that this object is passed into, however when I try to use that same object from a JDialog, I get the error "COM object method returns error code: 0x8001010E; The application called an interface that was marshalled for a different thread." I know the problem is that the COM object was created on another thread, but I don't know how to get it to work on my Swing thread. I've tried experimenting with the OleMessageLoop but can't make that work either.
Here is what is in my Java COM Server class:
// configuration is VB COM object
public void configure(_Configuration configuration) {
// This succeeds
System.out.println("Name: " + configuration.getName().getValue());
TestDialog dlg = new TestDialog(configuration);
dlg.setVisible(true);
}
And this is what I have inside my dialog when a button is pressed:
private void btTest_actionPerformed(ActionEvent e) {
// This fails
System.out.println("Name: " + configuration.getName().getValue());
}
Any ideas? I'm using the latest 2.4 ComfyJ libraries.
Thanks,
Dan
Hi, Dan
You should use OleMessageLoop.bindObject for this task - it creates a proxy object that always execute function calls in the scope of right OleMessageLoop. There is a code example:
private _Configuration configurationProxy;
// configuration is VB COM object
public void configure(_Configuration configuration) {
configurationProxy = (_Configuration) OleMessageLoop.getInstance().bindObject(configuration);
System.out.println("Name: " + configurationProxy.getName().getValue());
TestDialog dlg = new TestDialog(configurationProxy);
dlg.setVisible(true);
}
private void btTest_actionPerformed(ActionEvent e) {
// This fails
System.out.println("Name: " + configurationProxy.getName().getValue());
}
Regards,
Vadim Ridosh
Hi Vadim,
I actually tried that exact code already. Not only does it not work in my dialog, but it also doesn't work in my configure method either. For both cases I get the marshalling error.
Dan
Hi Dan,
I think roots of the problem can be in wrong place (thread, actually) where you called bindObject function. Try to call it directly after you obtained _Configuration pointer from VB code. If this won't help, could you please send me more sample code to reproduce the problem?
Regards,
Vadim Ridosh
Hi Dan,
It seems these pointers are actually marshaled for the thread other then thread where OleMessageLoop works. To workaround this, you should use COM marshaling functions:
// This method receives interfaces from VB code
public void TestProfile(_DriverProfile driverProfile) {
try {
// Create stream to marshal interface
IStream strm = OleFunctions.coMarshalInterThreadInterfaceInStream(new IUnknownImpl(driverProfile));
TestDialog dlg = new TestDialog(strm); // Pass this stream to dialog
dlg.setVisible(true);
} catch (Throwable th) {
th.printStackTrace();
JOptionPane.showMessageDialog(null, th.getMessage());
}
}
public class TestDialog extends javax.swing.JDialog {
private IStream stream; // Stream is stored in the dialog
/** Creates new form TestDialog */
public TestDialog(IStream stream) {
super((javax.swing.JDialog)null, true);
initComponents();
this.stream = stream;
}
private void btnTestActionPerformed(java.awt.event.ActionEvent evt) {
ComFunctions.coInitialize(); // Initialize COM
IUnknownImpl unk = new IUnknownImpl();
stream.seek(new Int64(0l), new StreamSeek(StreamSeek.STREAM_SEEK_SET)); // Set Stream pointer to the beginning
OleFunctions.coUnmarshalInterface(stream, new IID(_DriverProfile.INTERFACE_IDENTIFIER), unk); // Unmarshal interface
_DriverProfile profileProxy = new _DriverProfileImpl(unk); // Call QI
System.out.println(profileProxy.getDriverName()); // It works now.
}
In this sample unmarshaling performed each time btnTestActionPerformed called. For performance reasons, this can be performed only once per thread, in this case unmarshaled pointer can be stored permanently (in thread local memory, for example). I did not included this in code to keep it simple.
Regards,
Vadim Ridosh