Hi all,
I was awaiting PB9 impatiently, as I was looking forward to have OOP tool ( no more "and it is not OOP right?" on university, heh ) able to produce COM servers to be used in other languages ... which would mean I could code in my precious PB and let others struggle with .NET languages.
So the thing I wanted to create is COM DLL to be used with C# ( MSVS 2005 Express ).
What I managed:
- Create DLL
- Use PBTYP to insert type library
- Register server using regsvr32
- In C# "Add reference / DummyCOM" succeeded without any complaints, intellisense sees methods
But the problem is C# does complain "The type does not have constructors declared".
What a weird thing? You can see I have constructor in my code:
#COMPILE DLL
#DIM ALL
#RESOURCE "COMServer.pbr"
#COM NAME "DummyCOM", 1.0
#COM TLIB ON
#COM DOC "DummyCOM"
#COM GUID GUID$("{9C41D1BB-3B61-4BA3-A1F1-6FC09A46D9BF}")
#INCLUDE "Win32API.inc"
GLOBAL ghInstance AS DWORD
FUNCTION LIBMAIN (BYVAL hInstance AS LONG, _
BYVAL fwdReason AS LONG, _
BYVAL lpvReserved AS LONG) AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
ghInstance = hInstance
FUNCTION = 1 'success!
CASE %DLL_PROCESS_DETACH
FUNCTION = 1 'success!
CASE %DLL_THREAD_ATTACH
FUNCTION = 1 'success!
CASE %DLL_THREAD_DETACH
FUNCTION = 1 'success!
END SELECT
END FUNCTION
CLASS MYCLASS GUID$("{065A1E0F-ACFD-42F8-8DC7-B135168D7C91}") AS COM
' -- Isn't this nice example of constructor :")
CLASS METHOD CREATE ALIAS "CREATE"()
MSGBOX "Created, yahoo"
END METHOD
INTERFACE GREETINGS GUID$("{AE6D5037-4C8C-471D-ACD5-2AAA664466B7}")
INHERIT IUNKNOWN
METHOD HELLO ALIAS "HELLO"()
MSGBOX "Hello"
END METHOD
METHOD CIAO ALIAS "CIAO"()
MSGBOX "CIAO"
END METHOD
END INTERFACE
END CLASS
But when I try following code in C# I get that silly error. Maybe it is because CREATE is out of INTERFACE so invisible somehow?
Quote
...
using DummyCOM;
...
MYCLASS x = new MYCLASS(); ' -- This fails :(
x.HELLO(); ' -- The hello method was correctly detected by intelisense
I am sorry I am bothering you with .NET stuff, but you can imagine I would be very happy coding everything in PB I trust, and let other use it from C# which I do not like.
Thanks,
Petr
COM classes don't have a constructor. Its lifetime is controlled by the AddRef and Release methods of the IUnknown interface, and its creation by the IClassfactory interface. If PB classes have a constructor, a destructor, and private and hidden methods, is just to allow some OOP programming, but these methods aren't referenced in the virtual table. If C# complains about the class not having a constructor, maybe it is confusing it with a .NET class.
Aha,
so maybe I should invoke it differentely.
Thanks a lot for your time José.
Petr
Petr,
When using my GDImage.DLL with C#, i am just doing the same than calling the good old FLAT API ;)
If you compare the GDImage Carousel C# and PB's demo you will see no difference.
I am encapsulating my own API into a dedicated C# class, i put my Win32 DLL in the same folder than my managed EXE and i am done.
Hi Patrice,
thanks. I know how to bind classic DLL, but I wanted to avoid the class definition on C# side.
That was the reason why to pick COM DLL instead of good old "normal" DLL under PowerBASIC.
Maybe it will be less work for me to provide C# wrapper class, but then the beauty of COM server is gone, will investigate further.
Petr
Hi Petr
Maybe this link will be useful
http://msdn.microsoft.com/en-us/library/ms973274.aspx
Regards - Carlo
Hi Carlo,
thanks for the help. That is very good article.
- I tried to create the same DLL as is in article like:
#COMPILE DLL "MSDNCom.DLL"
#DIM ALL
#RESOURCE "COMServer.pbr"
#COM NAME "DummyCOM", 1.0
#COM TLIB ON
#COM DOC "DummyCOM"
#COM GUID GUID$("{9C41D1BB-3B61-4BA3-A1F1-6FC09A46D9BF}")
CLASS MSDNComServer GUID$("{065A1E0F-ACFD-42F8-8DC7-B135168D7C91}") AS COM
INTERFACE IMSDNComServer GUID$("{AE6D5037-4C8C-471D-ACD5-2AAA664466B7}")
INHERIT IDISPATCH
METHOD SquareIt ALIAS "SquareIt"()
MSGBOX "It should square it here"
END METHOD
END INTERFACE
END CLASS
- I used TlbImp to create Interop.MSDNCom.DLL
- I used ildasm.exe to see everything looks the same as in article sample, it does
- I created sample similar to the provided, but still get that constructor problem
I will check the full C++ code again ( it looks very complex ), but so far I had no success.
Thanks,
Petr
Hello,
True.
This DLL can not be instanciated from .NET as a New object :
Dim j As New DummyCOM.MSDNCOMSERVER '=>> Impossible because there is a Private internal mechanism unavailable for .NET
But this coce is possible :
Dim j As DummyCOM.MSDNCOMSERVER
But... when we try to invoke the SquareIt() method then .NET crashes.
Same problems appear in VB6 and in VBA as well...
And please I don't want to use the late binding aka CreateObject(""), but plain and direct IDispatch interface :)
The latest PB release has updated the typelib issue.
A comserver can now be instantiated using new just fine.
(Early binding)
Hi Edwin,
thanks for letting us now - I can confirm I just recompiled code and now it works in MSVS C# 2008.
Petr
Quote from: Petr Schreiber on March 18, 2009, 07:32:44 AM
Hi Edwin,
thanks for letting us now - I can confirm I just recompiled code and now it works in MSVS C# 2008.
Petr
May be this enhancement was (also) due to my remarks onto the PB forum...