Seite 4 von 5

Verfasst: Montag 7. April 2008, 20:28
von EyDu
Wahrscheinlich hast du vorher einfach nur ein "import ctypes" vergessen.

Verfasst: Montag 7. April 2008, 20:29
von ne0h
Du musst die Module auch erstmal importieren, damit sie bekannt sind.

Also zuerst:

Code: Alles auswählen

import math
und dann

Code: Alles auswählen

dir(irgendwas)


ne0h

Verfasst: Montag 7. April 2008, 20:30
von ne0h
Warum bin ich immer zu langsam... :?

Verfasst: Montag 7. April 2008, 20:34
von gerold
sechsrad hat geschrieben:bei dir(ctypes) kommt "NameError: name 'ctypes' is not defined"
Man muss ``ctypes`` vorher importieren, bevor man es mit ``dir`` analysieren kann.

EDIT:
ne0h hat geschrieben:Warum bin ich immer zu langsam... :?
Und du glaubst, du bist langsam? ;-)

Verfasst: Montag 7. April 2008, 21:22
von HWK
Masaru hat geschrieben:So wie du das da versuchst sechsrad, funktioniert es bei mir auch nicht ...
Eine andere, meines Erachtens einfachere Variante, da die C-Funktionen nicht umständlich angepasst werden müssen, wäre mit restype:

Code: Alles auswählen

import ctypes

f = ctypes.cdll.LoadLibrary('test.dll')
f.mult.restype = ctypes.c_float
print f.mult(ctypes.c_float(34.3))
print 3.7 * 34.3
Hierbei kann dann sechsrads Original-DLL

Code: Alles auswählen

#include <math.h>

float mult(float n) {
float a;
a = n * 3.7;
return a;
}
verwendet werden.
MfG
HWK

Verfasst: Montag 7. April 2008, 22:22
von sechsrad
da kommt dieses als ergebnis : -1.#IND

mfg

Verfasst: Montag 7. April 2008, 22:27
von sechsrad
die variante von masaru funktioniert jetzt :

Code: Alles auswählen

#!/usr/bin/env python

from ctypes import *
f =cdll.LoadLibrary("test.dll")

ff=pointer(c_float())
tt=pointer(c_char_p())

b=c_float(10.0)
f.mult(b,ff)
print ff.contents.value

b=c_float(10.8)
f.div(b,ff)
print ff.contents.value

f.text(tt)
print tt.contents.value
und die dll:

Code: Alles auswählen

#include <math.h>

void mult(float n, float* r) {
*r=n*3.7;
} 

void div(float n, float* r) {
*r=n/2.0;
}

void text(int* r) {
char text[] = "hurra, es geht !\n";
*r=text;
}

ergebnis ist dieses hier :
D:/Python25/pythonw.exe -u "D:/Python25/test-py/dll/dll1.py"
37.0
5.40000009537
hurra, es geht !

Verfasst: Montag 7. April 2008, 22:51
von EyDu
sechsrad hat geschrieben:

Code: Alles auswählen

void text(int* r) {
char text[] = "hurra, es geht !\n";
*r=text;
}
Aua. Ich hoffe mal, dass nur dein Testcode so aussieht.

Verfasst: Montag 7. April 2008, 23:12
von sechsrad
aua, es ging nur darum, wie man text aus einer dll übertragen kann, aua.

das andere ergibt dann die feinarbeit. die funktion steht jetzt erstmal im vordergrund.

wie man dieses char jetzt ausfüllt, da gibt es ja verschiedene möglichkeiten in c.

eine textfunktion aus einer dll hatte ich hier im ganzen forum noch nicht gefunden.

es funktioniert erst einmal, das ist wichtig.

Verfasst: Montag 7. April 2008, 23:25
von audax
sechsrad hat geschrieben: eine textfunktion aus einer dll hatte ich hier im ganzen forum noch nicht gefunden.
Warum auch....das hier ist kein C-Forum.

du hast übrigens noch immer nicht diese unglaublich komplexen Rechnungen gezeigt, die in Python zu langsam sind.

Verfasst: Montag 7. April 2008, 23:29
von EyDu
sechsrad hat geschrieben:es funktioniert erst einmal, das ist wichtig.
Nur damit das klargestellt ist: es ist reiner Zufall, dass die text-Funktion funktioniert.

Verfasst: Dienstag 8. April 2008, 13:46
von sechsrad
nochmals danke für die hilfe mit einer dll in python einbinden.

mein ziel ist erreicht, klappt wunderbar mit allen was ich mir vorgestellt habe.

danke.

mfg

Nur damit das klargestellt ist: es ist reiner Zufall, dass die text-Funktion funktioniert.
ich meine, eine zeigerübergabe ist kein zufall, ich glaube(gehe auch in die kirche) das ist die einfachste lösung.

Verfasst: Dienstag 8. April 2008, 14:36
von EyDu
sechsrad hat geschrieben:ich meine, eine zeigerübergabe ist kein zufall, ich glaube(gehe auch in die kirche) das ist die einfachste lösung.
Das stimmt, das Übergebens eines Zeigers ist kein Zufall. Jedoch befindet sich der String auf dem Stack und damit ist nach Abarbeitung der Funktion auch der Inhalt auf den der Zeiger zeigt undefiniert.

Verfasst: Dienstag 8. April 2008, 19:45
von HWK
sechsrad hat geschrieben:da kommt dieses als ergebnis : -1.#IND

mfg
Ich weiß ja nicht, was Du da gemacht hast, bei mir kommt jedenfalls folgendes heraus:

Code: Alles auswählen

C:\Programme\Python24\Scripts\Test>type test.py
#!/usr/bin/env python

import ctypes

f = ctypes.cdll.LoadLibrary('test.dll')
f.mult.restype = ctypes.c_float
print f.mult(ctypes.c_float(34.3))
print 3.7 * 34.3

C:\Programme\Python24\Scripts\Test>test.py
126.909996033
126.91
MfG
HWK

Verfasst: Mittwoch 9. April 2008, 11:20
von BlackJack
@EyDu: Die Zeichenkette sollte sich nicht auf dem Stack befinden. Das würde ja bedeuten, dass die Zeichenkette bei jedem Aufruf von woanders dort hin kopiert werden müsste, und da literale Zeichenketten "read only" sind, wäre das ziemlich unsinnig.

Aber die Funktion ist trotzdem total falsch. Erstens ist das Rückgabeargument vom Typ ``int*`` und dann wird nicht die Zeichenkette zurückgegeben, sondern die Adresse als Zahl. Wenn man den Rückgabeargumenttyp auf ``char*`` korrigieren würde, ist es immer noch nicht richtig, da dann versucht würde einen Zeiger in ein Zeichen zu konvertieren.

Verfasst: Mittwoch 9. April 2008, 13:25
von HWK
Und meine Variante:
Python-Script

Code: Alles auswählen

#!/usr/bin/env python

import ctypes

f = ctypes.cdll.LoadLibrary('test.dll')
f.mult.restype = ctypes.c_float
f.div.restype = ctypes.c_float
f.text.restype = ctypes.c_char_p
print f.mult(ctypes.c_float(10))
print f.div(ctypes.c_float(10.8))
print f.text()
DLL

Code: Alles auswählen

#include <math.h>

char TEXT[] = "Das ist ein Test\n";

float mult(float n) {
    return 3.7 * n;
}

float div(float n) {
    return n / 2;
}

char* text() {
    return TEXT;
}
Ausgabe

Code: Alles auswählen

>C:\Programme\Python24\pythonw -u "test.py"
37.0
5.40000009537
Das ist ein Test

>Exit code: 0
MfG
HWK

Verfasst: Mittwoch 9. April 2008, 14:25
von EyDu
BlackJack hat geschrieben:@EyDu: Die Zeichenkette sollte sich nicht auf dem Stack befinden. Das würde ja bedeuten, dass die Zeichenkette bei jedem Aufruf von woanders dort hin kopiert werden müsste, und da literale Zeichenketten "read only" sind, wäre das ziemlich unsinnig.
Das mag ja durchaus sein, dass eine Compiler in diesem Fall optimiert, aber im allgemeinen Fall kann man nicht davon ausgehen:

Code: Alles auswählen

void text(int* r) { 
char text[] = "hurra, es geht !\n";
text[4] = **a random character**;
*r=text; 
}

Verfasst: Mittwoch 9. April 2008, 19:40
von sechsrad
übergabestring, erweiterung,rückgabe

python-code:

Code: Alles auswählen

   
#!/usr/bin/env python

from ctypes import *
f =cdll.LoadLibrary("test.dll")

tt=pointer(c_char_p())
text=c_char_p("dies ist ein text")

f.text_out_in(text,tt)
print tt.contents.value
---------------------------------------------
print-ausgabe:

dies ist ein text ,es geht !
----------------------------------------------

dll:

Code: Alles auswählen

void text_out_in(char* text, int* r){
    char neustr[12]=" ,es geht!\0";
    strcat (text,neustr);
    *r=text;
}
[/code]

Verfasst: Mittwoch 9. April 2008, 19:53
von EyDu
Jetzt schreibst du irgendwo in der Gegend rum. Du musst schon einen String übergeben, der ausreichend Platz für das Ergebnis hat.

Und du bist dir wirklich sicher, dass du deine Programme mit C "optimieren" willst?

Verfasst: Mittwoch 9. April 2008, 20:41
von HWK
EyDu hat geschrieben:
BlackJack hat geschrieben:@EyDu: Die Zeichenkette sollte sich nicht auf dem Stack befinden. Das würde ja bedeuten, dass die Zeichenkette bei jedem Aufruf von woanders dort hin kopiert werden müsste, und da literale Zeichenketten "read only" sind, wäre das ziemlich unsinnig.
Das mag ja durchaus sein, dass eine Compiler in diesem Fall optimiert, aber im allgemeinen Fall kann man nicht davon ausgehen:

Code: Alles auswählen

void text(int* r) { 
char text[] = "hurra, es geht !\n";
text[4] = **a random character**;
*r=text; 
}
BlackJack hat schon recht, wie man hier am Assemblercode von

Code: Alles auswählen

char* text() {
    char TEXT[] = "Das ist ein Test\n";
    return TEXT;
}
in Mingw sieht:

Code: Alles auswählen

6ABC11AC  ASCII "Das ist ein Test\n",0
6ABC11BE  PUSH EBP
6ABC11BF  MOV EBP,ESP
6ABC11C1  SUB ESP,28
6ABC11C4  MOV EAX,DWORD PTR DS:[6ABC11AC]
6ABC11C9  MOV DWORD PTR SS:[EBP-28],EAX
6ABC11CC  MOV EAX,DWORD PTR DS:[6ABC11B0]
6ABC11D1  MOV DWORD PTR SS:[EBP-24],EAX
6ABC11D4  MOV EAX,DWORD PTR DS:[6ABC11B4]
6ABC11D9  MOV DWORD PTR SS:[EBP-20],EAX
6ABC11DC  MOV EAX,DWORD PTR DS:[6ABC11B8]
6ABC11E1  MOV DWORD PTR SS:[EBP-1C],EAX
6ABC11E4  MOV AX,WORD PTR DS:[6ABC11BC]
6ABC11EA  MOV WORD PTR SS:[EBP-18],AX
6ABC11EE  LEA EAX,DWORD PTR SS:[EBP-28]
6ABC11F1  LEAVE
6ABC11F2  RETN
Das ist meines Erachtens gängiges Verhalten von C-Compilern. D.h. der Code wird aus dem Code-Segment immer in einen evtl. unterschiedlichen Bereich des Stacks kopiert. Probleme gibt es v.a. dann, wenn neue Funktionen aufgerufen werden. Diese können nämlich diesen Stackbereich überschreiben. Nicht umsonst warnt deshalb der C-Compiler, dass hier die Adresse einer lokalen Variable übergeben wird.
MfG
HWK