• Welcome to Jose's Read Only Forum 2023.
 

Calling .NET classes from PowerBASIC

Started by José Roca, February 24, 2009, 11:09:37 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

José Roca

 
To use .NET classes with PowerBASIC you have to register the assembly as a  COM object with the regasm.exe tool.

Quote
The Assembly Registration tool reads the metadata within an assembly and adds the necessary entries to the registry, which allows COM clients to create .NET Framework classes transparently. Once a class is registered, any COM client can use it as though the class were a COM class. The class is registered only once, when the assembly is installed. Instances of classes within the assembly cannot be created from COM until they are actually registered.
http://msdn.microsoft.com/en-us/library/tzat5yw6(VS.71).aspx

The following example creates an instance of the "System.Net.WebClient" class to download a picture from an URI and save it to a file. If system.dll is not still registered in your system, you have to do it first using regasm.exe. Both regasm.exe and system.dll are located in C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 in my computer.


' ########################################################################################
' The following example creates an instance of the "System.Net.WebClient" class to
' download a picture from an URI and save it to a file.
' ########################################################################################

#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG

   LOCAL owc AS DISPATCH
   LOCAL vAddress AS VARIANT
   LOCAL vFileName AS VARIANT

   owc = NEWCOM "System.Net.WebClient"

   IF ISOBJECT(owc) THEN
      TRY
         vAddress = "http://www.jose.it-berater.org/webpages_images/h_2.jpg"
         vFileName = EXE.Path$ & "h_2.jpg"
         OBJECT CALL owc.DownloadFile(vAddress, vFileName)
         owc = NOTHING
         MSGBOX "Picture saved"
      CATCH
         IF OBJRESULT = &H80020009 THEN
            MSGBOX "Error &H" & HEX$(IDISPINFO.CODE) & $CRLF & IDISPINFO.DESC$
         ELSE
            MSGBOX "Error &H" & HEX$(OBJRESULT)
         END IF
      END TRY
   END IF

END FUNCTION


Petr Schreiber

Thank you José,

I tried it on PC with .NET 3.5 installed and it worked well.


Petr
AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

Patrice Terrier

José,

I didn't try it yet, but for sure that is a very useful tutorial.

Thank you!

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Petr Schreiber

#3
Nice,

not only .NET core libraries, but all "ClassLibraries" created by programmers in MSVS can be called in PB.

If anybody is interested, in MSVS C# 2008 Express you just:

  • Create ClassLibrary project
  • In project options /  Build / check "Register for COM interop"
  • In assembly info make sure that ComVisible is enabled: "[assembly: ComVisible(true)]"
  • Build the library

Worked well, tried even returning values. I built it as 3.5 assembly to see if it works just for 2.0, but no problem.
Still not sure how to make methods visible for COM Browser / TypeLibBrowser, but that is detail.

Thanks José, I would never believe it is possible :)


Petr
AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

José Roca

#4
 
Quote
Still not sure how to make methods visible for COM Browser / TypeLibBrowser, but that is detail.

I don't know if it is possible. Unless there is a way unknown to me, it generates dispatch only interfaces that can only be used with late binding. But at least, it works. And TRY/END TRY can be used to catch exceptions, and IDISPINFO can be used to retrieve the error code and description when OBJRESULT returns %DISP_E_EXCEPTION (&H80020009&).

José Roca

 
Well. Apparently you can create dual interfaces adding another attribute to all your public classes:


VB.NET: <ClassInterface(ClassInterfaceType.AutoDual)>
C#:     [ClassInterface(ClassInterfaceType.AutoDual)]


Petr Schreiber

José Roca Rocs again!

Good tip, it works perfectly now.
I can even see ( and use ) methods it inherits from System.Object, such as ToString().
Just have to not forget using ACODE$ for converting string values :)


Thank you,
Petr

AMD Sempron 3400+ | 1GB RAM @ 533MHz | GeForce 6200 / GeForce 9500GT | 32bit Windows XP SP3

psch.thinbasic.com

José Roca

 
Here is the link for the .NET Framework 4:
http://msdn.microsoft.com/en-us/library/tzat5yw6.aspx

Quote
Just have to not forget using ACODE$ for converting string values

This, of course, no longer applies to PBWIN 10 / PBCC 6, that have native unicode support.

Mike Doty

#8
Automatically register system.dll
Thank you!  Opens up so many possibilities.

#DIM ALL
REM #INCLUDE "win32api.inc" 'for shellexecute
#INCLUDE "shellapi.inc" 'for shellexecute

'http://www.jose.it-berater.org/smfforum/index.php?topic=3053.0
' ########################################################################################
' The following example creates an instance of the "System.Net.WebClient" class to
' download a picture from an URI and save it to a file.
' ########################################################################################

FUNCTION Regasm AS LONG 'only need this code once
  LOCAL sDllPath AS STRING
  sDllPath = "C:\Windows\Microsoft.NET\Framework\v2.0.50727\"
  IF ISFILE(sDllPath + "system.dll") THEN
   SHELL sDLLPath + "regasm.exe system.dll
   FUNCTION = 1 'success
  ELSE
   ? "system.dll not found"
  END IF
END FUNCTION

FUNCTION PBMAIN () AS LONG
   IF RegAsm = 0 THEN EXIT FUNCTION
   LOCAL zFileName AS STRINGZ * 256
   LOCAL owc AS DISPATCH
   LOCAL vAddress AS VARIANT
   LOCAL vFileName AS VARIANT

   owc = NEWCOM "System.Net.WebClient"

   IF ISOBJECT(owc) THEN
      TRY
         vAddress = "http://www.jose.it-berater.org/webpages_images/h_2.jpg"
         vFileName = EXE.PATH$ & "h_2.jpg"
         OBJECT CALL owc.DownloadFile(vAddress, vFileName)
         owc = NOTHING
         'display using default viewer
         zFileName = EXE.PATH$ & "h_2.jpg"
         ShellExecute (%NULL, "OPEN", zFileName, BYVAL %NULL, CURDIR$, %SW_SHOWNORMAL)
      CATCH
         IF OBJRESULT = &H80020009 THEN
            MSGBOX "Error &H" & HEX$(IDISPINFO.CODE) & $CRLF & IDISPINFO.DESC$
         ELSE
            MSGBOX "Error &H" & HEX$(OBJRESULT)
         END IF
      END TRY
   ELSE
     ? "ISOBJECT FAILED"
   END IF
END FUNCTION'