ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von Mok »

Hallo!
Mein Programm ruft eine Prozedur aus einer DLL auf, welche ein paar CPU-Flags (SSE1 - SSE3, SSSE3, MMX und Co.) abfragt und in einer Map abspeichert. Für einen Fall wie diesen sind Maps ja wie gemacht. Das Problem daran: Wie kann ich die Map returnen, sodass ich sie im aufrufenden Programm verwenden kann? Und wenn's funktionieren würde, könnte man diese DLL nur in PureBasic nutzen, da der Purebasic-Typ 'Map' wohl in anderen Programmiersprachen genutzt werden kann.
Jetzt frage ich mich: Gibt es noch eine andere Datenstruktur/Möglichkeit, welche ich hier nutzen könnte, um die Flags zurückzugeben? Das ganze sollte möglichst ohne viel ADTs passieren (also jetzt eine eigene HashMap programmieren, welche man dann auch noch in jedem Ruferprogramm definieren muss). Zuvor hab ich's mit Strings gemacht, allerdings gleich wieder weggemacht, weil Effizienz = 0.

Hier noch ein (nicht funktionierender) Code:

Code: Alles auswählen

 ;DLL-Code
ProcedureDLL GetCpuFlags()
  ; Code großteils aus dem CodeArchiv
  Global mmx.b   = 0 ;MMX
  Global dnow.b  = 0 ;3DNow!
  Global ednow.b = 0 ;ext3DNow!
  Global cmov.b  = 0 ;CMovCC
  Global sse.b   = 0 ; SSE
  Global sse2.b  = 0 ;SSE2
  Global sse3.b  = 0 ;SSE3
  Global ssse3.b = 0 ;SSSE3
  Global SSE41.b = 0 ;SSE4.1
  Global SSE42.b = 0 ;SSE4.2

  Global Bit0.l  = $1
  Global Bit9.l  = $200
  Global Bit15.l = $8000
  Global Bit21.l = $200000
  Global Bit23.l = $800000
  Global Bit25.l = $2000000
  Global Bit26.l = $4000000
  Global Bit30.l = $40000000
  Global Bit31.l = $80000000
  Global SSE41b.l = $80000
  Global SSE42b.l = $100000
  
          
  
      !mov eax,1h
      !cpuid
      !test edx,[v_Bit23]
      !jz l_nommx
      !mov [v_mmx],1
  NOMMX:
      !test edx,[v_Bit25] 
      !jz l_nosse
      !mov [v_sse],1
  NOSSE:
      !test edx,[v_Bit26] 
      !jz l_nosse2
      !mov [v_sse2],1
  NOSSE2:
      !test ecx,[v_Bit0]
      !jz l_nosse3
      !mov [v_sse3],1    
  NOSSE3:
      !test ecx,[v_Bit9]
      !jz l_nossse3
      !mov [v_ssse3],1 
  NOSSSE3:
      !test edx,[v_Bit15]    
      !jz l_nocmov
      !mov [v_cmov],1
  NOCMOV:       
      !mov eax,80000000h
      !cpuid
      !cmp eax,80000000h
      !jbe l_noext
  
      !mov eax,80000001h
      !cpuid
      !or eax,eax
      !je l_noext
      !test edx,[v_Bit31] 
      !jz l_noext
      !mov [v_dnow],1
      !test edx,[v_Bit30]  
      !jz l_noext
      !mov [v_ednow],1
  NOEXT:
      !test ecx,[v_SSE41b]
      !jz l_nosse41
      !mov [v_SSE41], 1
  NOSSE41:
      !test ecx,[v_SSE42b]
      !jz l_nosse42
      !mov [v_SSE42], 1
  NOSSE42:

  NewMap m.b();
  m("MMX") = MMX
  m("3DNow") = dnow
  m("ext3DNow") = ednow
  m("CMov") = cmov
  m("SSE") = SSE
  m("SSE2") = SSE2
  m("SSE3") = SSE3
  m("SSE41") = SSE41
  m("SSE42") = SSE42
  m("SSSE3") = ssse3
  
  ProcedureReturn @m()
  EndProcedure

Code: Alles auswählen

;Programmcode
If OpenLibrary (0,"cpu.dll")
  Prototype.i _GetCpuFlags()
  Global GetCpuFlags._GetCpuFlags = GetFunction(0,"GetCpuFlags")
Endif

Structure CPU
  Architecture.l
  Cores.b
  Map *Flags.b()
EndStructure
Define.CPU Processor
Processor\Flags() = GetCpuFlags()
  
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von ts-soft »

Maps können nicht zurückgegeben werden, aber als Parameter können sie an Proceduren übergeben werden,
sollte unter umständen auch bei einer DLL funktionieren, einfach mal testen.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von STARGÅTE »

ProcedureDLL GetCpuFlags(Map m.b())
statt NewMap m.b() unten

und dann:

Define.CPU Processor
GetCpuFlags(Processor\Flags())
Zuletzt geändert von STARGÅTE am 18.03.2011 19:54, insgesamt 1-mal geändert.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Re: ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von Mok »

STARGÅTE hat geschrieben:ProcedureDLL GetCpuFlags(Map m.b())
statt NewMap m.b()
Gute Idee, wäre da selber garnicht draufgekommen :allright:
Aber wie sieht's, sagen wir mal in C++ aus? Wie soll ich da eine Map übergeben? (sag bloß std::map)
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von ts-soft »

In c++ steht die PB Map ja gar nicht zur Verfügung, ist dort also nicht nutzbar.
Gibt keinen DLL HashMap standard Programmiersprachenübergreifend, sowas
mußt Du Dir wohl selber basteln.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Kevin
Beiträge: 236
Registriert: 11.06.2007 12:55

Re: ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von Kevin »

Mok hat geschrieben:
STARGÅTE hat geschrieben:ProcedureDLL GetCpuFlags(Map m.b())
statt NewMap m.b()
Gute Idee, wäre da selber garnicht draufgekommen :allright:
Aber wie sieht's, sagen wir mal in C++ aus? Wie soll ich da eine Map übergeben? (sag bloß std::map)
so geht's es vielleicht:

Code: Alles auswählen

Structure CPU
  Architecture.l
  Cores.b
  Map Flags.b()
EndStructure

;DLL-Code
ProcedureDLL GetCpuFlags()
  ; Code großteils aus dem CodeArchiv
  Global mmx.b   = 0 ;MMX
  Global dnow.b  = 0 ;3DNow!
  Global ednow.b = 0 ;ext3DNow!
  Global cmov.b  = 0 ;CMovCC
  Global sse.b   = 0 ; SSE
  Global sse2.b  = 0 ;SSE2
  Global sse3.b  = 0 ;SSE3
  Global ssse3.b = 0 ;SSSE3
  Global SSE41.b = 0 ;SSE4.1
  Global SSE42.b = 0 ;SSE4.2

  Global Bit0.l  = $1
  Global Bit9.l  = $200
  Global Bit15.l = $8000
  Global Bit21.l = $200000
  Global Bit23.l = $800000
  Global Bit25.l = $2000000
  Global Bit26.l = $4000000
  Global Bit30.l = $40000000
  Global Bit31.l = $80000000
  Global SSE41b.l = $80000
  Global SSE42b.l = $100000
  
          
  
      !mov eax,1h
      !cpuid
      !test edx,[v_Bit23]
      !jz l_nommx
      !mov [v_mmx],1
  NOMMX:
      !test edx,[v_Bit25] 
      !jz l_nosse
      !mov [v_sse],1
  NOSSE:
      !test edx,[v_Bit26] 
      !jz l_nosse2
      !mov [v_sse2],1
  NOSSE2:
      !test ecx,[v_Bit0]
      !jz l_nosse3
      !mov [v_sse3],1    
  NOSSE3:
      !test ecx,[v_Bit9]
      !jz l_nossse3
      !mov [v_ssse3],1 
  NOSSSE3:
      !test edx,[v_Bit15]    
      !jz l_nocmov
      !mov [v_cmov],1
  NOCMOV:       
      !mov eax,80000000h
      !cpuid
      !cmp eax,80000000h
      !jbe l_noext
  
      !mov eax,80000001h
      !cpuid
      !or eax,eax
      !je l_noext
      !test edx,[v_Bit31] 
      !jz l_noext
      !mov [v_dnow],1
      !test edx,[v_Bit30]  
      !jz l_noext
      !mov [v_ednow],1
  NOEXT:
      !test ecx,[v_SSE41b]
      !jz l_nosse41
      !mov [v_SSE41], 1
  NOSSE41:
      !test ecx,[v_SSE42b]
      !jz l_nosse42
      !mov [v_SSE42], 1
  NOSSE42:

*CPU.CPU=AllocateMemory(SizeOf(CPU))
InitializeStructure(*CPU, CPU)

 *CPU\Flags("MMX") = MMX
 *CPU\Flags("3DNow") = dnow
 *CPU\Flags("ext3DNow") = ednow
 *CPU\Flags("CMov") = cmov
 *CPU\Flags("SSE") = SSE
 *CPU\Flags("SSE2") = SSE2
 *CPU\Flags("SSE3") = SSE3
 *CPU\Flags("SSE41") = SSE41
 *CPU\Flags("SSE42") = SSE42
 *CPU\Flags("SSSE3") = ssse3
  
  ProcedureReturn *CPU
  EndProcedure

ProcedureDLL CPUResetMap(*CPU.CPU)
  ProcedureReturn ResetMap(*CPU\Flags())
EndProcedure
ProcedureDLL.s CPUKey(*CPU.CPU)
  ProcedureReturn MapKey(*CPU\Flags())
EndProcedure
ProcedureDLL CPUFlag(*CPU.CPU,element$="")
  If element$
    ProcedureReturn *CPU\Flags(element$)
  Else
    ProcedureReturn *CPU\Flags()
  EndIf
EndProcedure
ProcedureDLL CPUNextElement(*CPU.CPU)
  ProcedureReturn NextMapElement(*CPU\Flags())
EndProcedure
ProcedureDLL CPUFree(*CPU.CPU)
  FreeMemory(*CPU)
EndProcedure

Define.CPU *Processor
*Processor = GetCpuFlags()

CPUResetMap(*Processor)
While CPUNextElement(*Processor)
  Debug CPUKey(*Processor) + ": " + Str(CPUFlag(*Processor))
Wend

Debug ""
Debug "MMX: "+Str(CPUFlag(*Processor,"SSE3"))
Debug "SSE3: "+Str(CPUFlag(*Processor,"SSE3"))

CPUFree(*Processor)
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: ProcedureDLL: Map zurückgeben, bzw. Alternative zu Maps

Beitrag von mk-soft »

Bei Übergabe von Arrays an C++ oder dotNet würde ich "Variant von Type Array" empfehlen.
Das Aufräumen des speichers übernimmt dann auch das Gabage von C++ oder dotNet.

Code: Alles auswählen

Declare Unicode Function fcName Lib "PB.dll" (ByRef MyArray As Object) As Int32 ' hResult
Dim MyArray() as Object
Bei C++ muss es ähnlich sein

Code: Alles auswählen

IncludeFile "..\Funktionen\Varianthelper_Include.pb"

ProcedureDLL GetDaten_ArrayOfVariant(*var.variant)
  
  Protected *array.SAFEARRAY
  
  ; Falls noch Daten in der übergebenen variable vorhanden sind, diese löschen
  VariantClear(*var)
  ; Array erstellen (0..9)
  *array = saCreateSafeArray(#VT_VARIANT, 0, 10)
  ; Daten von array füllen
  V_STR(SA_VARIANT(*array, 0)) = T_BSTR("Hallo Welt")
  V_BOOL(SA_VARIANT(*array, 1)) = T_BOOL(#True)
  V_FLOAT(SA_VARIANT(*array, 2)) = 99.9
  V_LONG(SA_VARIANT(*array, 3)) = 12345678
  V_DATE(SA_VARIANT(*array, 4)) = T_DATE(Date())
  ;....
  
  ; Safearray zuweisten
  V_ARRAY_VARIANT(*var) = *array
  
EndProcedure

ProcedureDLL GetDaten_ArrayOfString(*var.variant)
  
  Protected *array.SAFEARRAY
  
  ; Falls noch Daten in der übergebenen variable vorhanden sind, diese löschen
  VariantClear(*var)
  ; Array erstellen (1..10)
  *array = saCreateSafeArray(#VT_BSTR, 5, 10)
  ; Daten von array füllen
  For i = saLBound(*array) To saUBound(*array)
    SA_BSTR(*array, i) = T_BSTR("Zeile " + Str(i))
  Next
  ;....
  
  ; Safearray zuweisten
  V_ARRAY_STR(*var) = *array
  
EndProcedure


VariantHelper
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten