Hello people, I have probably a similar problem. Has anyone know how to resolve the problem?
Hello people, I have probably a similar problem. Has anyone know how to resolve the problem?
My Delphi is Enterprise - Berlin
The event (into the Delphi COM server) has string parameters and if the event is triggered with blank string values (empty strings '')(all or some of them), it will not be fired in C# program because an exception is raised. The raised exception message is: Invalid pointer.
but...
There no such problem if the clients application is a Delphi application. The Delphi client application works perfectly.
If the string parameter has only one character also, the event will be fired into the C# application without an exception.
Any ideas?
:(
https://stackoverflow.com/questions/22675815/com-event-not-triggered-in-c-sharp-for-delphi-com-objects-with-empty-values-in-s
My Delphi is Enterprise - Berlin
The event (into the Delphi COM server) has string parameters and if the event is triggered with blank string values (empty strings '')(all or some of them), it will not be fired in C# program because an exception is raised. The raised exception message is: Invalid pointer.
but...
There no such problem if the clients application is a Delphi application. The Delphi client application works perfectly.
If the string parameter has only one character also, the event will be fired into the C# application without an exception.
Any ideas?
:(
https://stackoverflow.com/questions/22675815/com-event-not-triggered-in-c-sharp-for-delphi-com-objects-with-empty-values-in-s
Hm... maybe the answer is in the usage of SysAllocString - a method which I not use in this case. I'll post the results tomorrow - for now bye from me.
ReplyDeletePerhaps related: stackoverflow.com - COM Server sends empty string which is converted to a NULL pointer - allocating an empty string might help
ReplyDeleteLikely a string lifetime management thing on either side of the interface. COM uses PChar so you need to ensure the string backing storage lives long enough for the event but short enough not to cause a memory leak.
ReplyDeleteMake a reproducible case showing the full code on both sides of the interface.
Jeroen Wiert Pluimers Er, COM strings are BSTR, not PChar, allocated on the shared COM heap by calling SysAllocString.
ReplyDeleteDobrin Petkov This is surely easy to answer with a minimal reproduction.
ReplyDeleteDavid Heffernan Yup, you are right. I mixed up COM with P/Invoke. Reproducible case still applies.
ReplyDeleteridl source:
ReplyDeleteHello - sorry for the delayed answer. Here is an example of my Delphi COM Server code:
ridl source:
-----------------------------------------
dispinterface ICMYCOMServerEvents
{
properties:
methods:
...
[id(0x000000D4)]
HRESULT OnSendCommand([in] BSTR Command, [in] BSTR hex_Header, [in] BSTR hex_Data, [in] BSTR hex_Footer, [in] BSTR human_Data);
...
};
---------------------------------------
TLB source:
-----------------------------------------
ICMYCOMServerEvents = dispinterface
...
function OnSendCommand(const Command: WideString; const hex_Header: WideString;
const hex_Data: WideString; const hex_Footer: WideString;
const human_Data: WideString): HResult; dispid 212;
-----------------------------------------
Implementation:
-----------------------------------------
procedure TCMYCOMServerEvent.send_SendCommand(const Command, hex_Header, hex_Data, hex_Footer, human_Data: WideString);
var
Enum : IEnumConnections;
ConnectData : TConnectData;
Fetched : Cardinal;
begin
Enum := GetEnumerator;
if Enum <> nil then
while Enum.Next(1, ConnectData, @Fetched) = S_OK do
if ConnectData.pUnk <> nil then
(ConnectData.pUnk as ICMYCOMServerEvents).OnSendCommand(
Command,
hex_Header,
hex_Data,
hex_Footer,
human_Data);
end;
-----------------------------------------
For example If hex_Data or human_Data are empty strings - this code raise an exception if client side is C# application.
No problems with Delphi clients
at the C# side - this is enough:
ReplyDelete...
_serv = new CMYCOMServer();
if (_serv != null)
{
...
this.serv.OnSendCommand += Serv_OnSendCommand;
}
...
private void Serv_OnSendCommand(string Command, string hex_Header, string hex_Data, string hex_Footer, string human_Data)
{
//
}
...
Note: C# code is not mine.
Delphi events fired as a result of execution of some commands to the device via RS-232. The client side can log data into the file or show the data (or something else).
ReplyDeleteThis isn't complete. We can't execute this because of that. Read this http://sscce.org
ReplyDeleteDavid Heffernan You are right - sorry for that.
ReplyDeleteThe usage of "SysAllocString('');" not helped much - Delphi raise the same exception but I found how to resolve (or avoid) the problem.
ReplyDelete-
My solution:
1. Change the ridl description of parameters to [in, out].
- From:
-- "HRESULT OnSendCommand([in] BSTR Command, [in] BSTR hex_Header, [in] BSTR hex_Data, [in] BSTR hex_Footer, [in] BSTR human_Data);"
- to the:
-- "HRESULT OnSendCommand([in, out] BSTR* Command, [in, out] BSTR* hex_Header, [in, out] BSTR* hex_Data, [in, out] BSTR* hex_Footer, [in, out] BSTR* human_Data);"
2. Update the reference into the C# project;
3. Change the implementation into the C# code to:
private void Serv_OnSendCommand(ref string Command, ref string hex_Header, ref string hex_Data, ref string hex_Footer, ref string human_Data)
{
string tmp_Command = Command != null ? Command : "";
string tmp_hex_Header = hex_Header != null ? hex_Header : "";
string tmp_hex_Data = hex_Data != null ? hex_Data : "";
string tmp_hex_Footer = hex_Footer != null ? hex_Footer : "";
string tmp_human_Data = human_Data != null ? human_Data : "";
...
and use tmp_xx values!
That is all for now.
Dobrin Petkov which very much points the root cause being a string lifetime management issue.
ReplyDeleteNote that the change of parameter totally alters the meaning of your interface. And it steps away from solving G your root cause, which now will bite you in a different place at a time you're even less prepared for it.
You've not fixed anything there at all. You've merely swept the problem under the carpet.
ReplyDeleteAll you are right - this is not a proper fix. Avoiding of the problem for now is more close to the situation as description of my temporary solution.
ReplyDeleteBut I can't share the entire project. I will try to make some new example projects (according to the recommendations of David Heffernan) after few days and will post them here.
Dobrin Petkov now you are moving in the right direction. Well done. I am
ReplyDeletelooking forward to your new posts.
Attila Kovacs stop guessing
ReplyDelete