C++ -> COM +> C#

22/04/2008 - 19:50 von Matthias Truxa | Report spam
Hallo an alle, die sich sowohl in C# als auch und v.a. in C++ auskennen,
wobei ich mich leider zu letzteren nicht zàhlen kann. Ich versuche seit
einigen Stunden einen COM-Aufruf zum Laufen zu bringen und weiß partout
nicht, was ich falsch machen könnte.

Ich habe eine .NET Klasse, die ComVisible ist.
Diese möchte ich von C++ aus (eine Fremdsprache für mich) instantiieren und
folgende Methode aufrufen:

[ComVisible(true), Guid("69e922eb-bb27-46b7-96bd-4391d32b441d")]
public class MetatraderBridge
{
public string ExecuteBatch(string batch)
{
MessageBox.Show(batch); // gibt nur leere messagebox aus, mit
int statt string klappts hingegen
return "Test";
}
}

Ich muss also von C++ aus sowohl einen string übergeben als auch erhalten
können. In meiner C++ routine erhalte ich einen char* und gebe auch solch
einen wieder zurück (zwingend). Die Instantiierung funzt soweit, der Aufruf
funktioniert auch, allerdings erhalte ich in meiner .NET-Klasse partout
nicht den übergebenen Wert (sondern einen Leerstring).

Hier der C++ Code.

EXPFUNC char* __stdcall CallBridge(char* progId, char* batch)
{
IDispatch* bridge = NULL;
USES_CONVERSION;
LPCOLESTR oleProgId = A2COLE(progId);
CLSID cls;
CLSIDFromProgID(oleProgId, &cls);
hr = CoCreateInstance(cls, NULL, CLSCTX_INPROC_SERVER, __uuidof(IDispatch),
(void**)&bridge); // funzt

VARIANT result;
VariantInit(&result);
DISPID dispid;

/****** Um diese Parameterübergabe geht es ****
VARIANTARG _args[1];
VariantInit(&_args[0]);
DISPPARAMS args = {_args, NULL, 1, 0};
args.rgvarg[0].vt = VT_BSTR;
args.rgvarg[0].bstrVal = A2OLE(batch); // funzt auch nicht mit L"const"
args.cArgs = 1;
args.cNamedArgs = 0;

LPOLESTR method = OLESTR("ExecuteBatch");
HRESULT hr = 0;
hr = bridge->GetIDsOfNames(IID_NULL, &method, 1, LOCALE_USER_DEFAULT,
&dispid);
hr = bridge->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD,
&args, &result, NULL, NULL); // invoke an sich funzt
return OLE2A(result.bstrVal);
}


Kann mir bitte jemand weiter helfen? Wüsste zu gern, was ich wie marshallen
muss um das zum Laufen zu bringen.

Besten Dank im Voraus;
Matt
 

Lesen sie die antworten

#1 Matthias Truxa
22/04/2008 - 20:59 | Warnen spam
I got it, i got it! :D

args.rgvarg[0].vt = VT_BSTR;
args.rgvarg[0].bstrVal = SysAllocString(A2COLE(batch));

will do.

damn.. tricky.


"Matthias Truxa" schrieb im Newsbeitrag
news:O$
Hallo an alle, die sich sowohl in C# als auch und v.a. in C++ auskennen,
wobei ich mich leider zu letzteren nicht zàhlen kann. Ich versuche seit
einigen Stunden einen COM-Aufruf zum Laufen zu bringen und weiß partout
nicht, was ich falsch machen könnte.

Ich habe eine .NET Klasse, die ComVisible ist.
Diese möchte ich von C++ aus (eine Fremdsprache für mich) instantiieren
und folgende Methode aufrufen:

[ComVisible(true), Guid("69e922eb-bb27-46b7-96bd-4391d32b441d")]
public class MetatraderBridge
{
public string ExecuteBatch(string batch)
{
MessageBox.Show(batch); // gibt nur leere messagebox aus, mit
int statt string klappts hingegen
return "Test";
}
}

Ich muss also von C++ aus sowohl einen string übergeben als auch erhalten
können. In meiner C++ routine erhalte ich einen char* und gebe auch solch
einen wieder zurück (zwingend). Die Instantiierung funzt soweit, der
Aufruf funktioniert auch, allerdings erhalte ich in meiner .NET-Klasse
partout nicht den übergebenen Wert (sondern einen Leerstring).

Hier der C++ Code.

EXPFUNC char* __stdcall CallBridge(char* progId, char* batch)
{
IDispatch* bridge = NULL;
USES_CONVERSION;
LPCOLESTR oleProgId = A2COLE(progId);
CLSID cls;
CLSIDFromProgID(oleProgId, &cls);
hr = CoCreateInstance(cls, NULL, CLSCTX_INPROC_SERVER,
__uuidof(IDispatch), (void**)&bridge); // funzt

VARIANT result;
VariantInit(&result);
DISPID dispid;

/****** Um diese Parameterübergabe geht es ****
VARIANTARG _args[1];
VariantInit(&_args[0]);
DISPPARAMS args = {_args, NULL, 1, 0};
args.rgvarg[0].vt = VT_BSTR;
args.rgvarg[0].bstrVal = A2OLE(batch); // funzt auch nicht mit L"const"
args.cArgs = 1;
args.cNamedArgs = 0;

LPOLESTR method = OLESTR("ExecuteBatch");
HRESULT hr = 0;
hr = bridge->GetIDsOfNames(IID_NULL, &method, 1, LOCALE_USER_DEFAULT,
&dispid);
hr = bridge->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, &args, &result, NULL, NULL); // invoke an sich funzt
return OLE2A(result.bstrVal);
}


Kann mir bitte jemand weiter helfen? Wüsste zu gern, was ich wie
marshallen muss um das zum Laufen zu bringen.

Besten Dank im Voraus;
Matt

Ähnliche fragen