einbinden vom c und c++

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

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
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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; 
}
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

ü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]
Zuletzt geändert von sechsrad am Donnerstag 10. April 2008, 07:50, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

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
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich habe auch nie behauptet, dass ein Compiler dies nicht optimieren kann, man darf nur nicht davon ausgehen. Der gcc macht es zum Beispiel nicht:

Code: Alles auswählen

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

int main(void) { }

Code: Alles auswählen

C:\Dokumente und Einstellungen\Sebastian\Desktop\test>gcc test.c
test.c: In function `text':
test.c:3: warning: function returns address of local variable
Macht der C-Standard zu diesem Sonderfall eventuell irgendwelche Aussagen?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

EyDu hat geschrieben:Ich habe auch nie behauptet, dass ein Compiler dies nicht optimieren kann, man darf nur nicht davon ausgehen. Der gcc macht es zum Beispiel nicht:

Code: Alles auswählen

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

int main(void) { }

Code: Alles auswählen

C:\Dokumente und Einstellungen\Sebastian\Desktop\test>gcc test.c
test.c: In function `text':
test.c:3: warning: function returns address of local variable
Macht der C-Standard zu diesem Sonderfall eventuell irgendwelche Aussagen?
Das verstehe ich jetzt nicht ganz. Mein Beispiel ist ja mit dem gcc von Mingw kompiliert. Man sieht dabei, dass der String in eine lokale Variable auf den Stack kopiert wird. Dies sollte ja auch so sein. Eine Optimierung liegt m.E. hier nicht unbedingt vor. Dass der String auf dem Stack liegt, führt zu folgenden Problemen:
1. Er kann immer an einer anderen Speicheradresse liegen, was BlackJack bereits sagte.
2. Er kann bei nachfolgenden Funktionsaufrufen evtl. überschrieben werden.
Kann es sein, dass Du es mit

Code: Alles auswählen

char* text() { 
    static char TEXT[] = "Das ist ein Test\n"; 
    return TEXT; 
}
verwechselst?
MfG
HWK
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann sind wir uns doch einig. Mir ging es um den bei dir zweiten Punkt. Ich wollte doch nur zum Ausdruck bringen, dass damit das Ergebnis von "text" zwar einen vernünftigen Pointer liefert, dieser jedoch nicht unbedingt den String "Das ist ein Test\n" repräsentiert, da dieser (String) auf dem Stack liegt und u. U. überschrieben wird.

Oder anders herum: Ich wollte nicht zum Ausdruck bringen, dass der "original" String verändert wird (wie man ja auch gut am ASM-Code sehen kann), sondern dass die Daten auf die der zurückgegebene Pointer zeigt nicht zuverlässlich sind.

EDIT: Oder als Code:

test.c

Code: Alles auswählen

char* spam() {
    char spam[] = "SPAM";
    return spam;
}

char* eggs() {
    char eggs[] = "EGGS";
    return eggs;
}
test.py:

Code: Alles auswählen

import ctypes

dll = ctypes.cdll.LoadLibrary("test.dll")

spam = dll.spam()
eggs = dll.eggs()

print ctypes.c_char_p(spam)
print ctypes.c_char_p(eggs)
Ausgabe:

Code: Alles auswählen

>>> 
c_char_p('EGGS')
c_char_p('EGGS')
>>> 
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

Und du bist dir wirklich sicher, dass du deine Programme mit C "optimieren" willst?
es geht mir hier jetzt zur zeit nicht um die optimierung, sondern den einfachen weg mit nur einem string zurückgeben zu erweitern , einen string entgegen zunehmen , erweitern und dann zurückgeben, weil dieses erste stringbeispiel ein bisschen pipifax war.

und die theorie des zufälligen funktionieren zu zerstreuen.
soviel zufall kann nicht sein.

mfg
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

char* spam() {
char spam[] = "SPAM";
return spam;
}

char* eggs() {
char eggs[] = "EGGS";
return eggs;
}
nur mit return, das kann nicht gut gehen.

mfg
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

sechsrad hat geschrieben:und die theorie des zufälligen funktionieren zu zerstreuen.
soviel zufall kann nicht sein.
Naja, das Spassige an C ist ja, dass wenn man in einen nicht vorgesehenen, aber schreibbaren Speicherbereich schreibt, man den Fehler erst bemerkt, wenn andere Programmteile in genau in den gleichen Bereich schreiben. Deswegen ist das zufaellige Funktionieren gerade bei kleineren Programmen nicht so ganz unwahrscheinlich.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

sechsrad hat geschrieben:nur mit return, das kann nicht gut gehen.
Ob man die Adresse nun per return zurückgibt, oder über einen Parameter, macht keinen unterschied.
sechsrad hat geschrieben:es geht mir hier jetzt zur zeit nicht um die optimierung, sondern den einfachen weg mit nur einem string zurückgeben zu erweitern , einen string entgegen zunehmen , erweitern und dann zurückgeben, weil dieses erste stringbeispiel ein bisschen pipifax war.
Dein String-Erweiterungs-Beispiel ist aber ebenso falsch.
sechsrad hat geschrieben:und die theorie des zufälligen funktionieren zu zerstreuen.
soviel zufall kann nicht sein.
Nee, klar. Einfach ganz fest dran glauben ;-)
lunar

EyDu hat geschrieben:Nee, klar. Einfach ganz fest dran glauben ;-)
Ist doch ok... der Glaube versetzt ja bekanntlich Berge, da sollte so ein billiges C-Char-Array ja ein Klacks sein ;)
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

EyDu hat geschrieben:Dann sind wir uns doch einig...
Prima!
sechsrad hat geschrieben:...nur mit return, das kann nicht gut gehen.
???
sechsrad hat geschrieben:...soviel zufall kann nicht sein.
Manchmal scheinbar doch.
MfG
HWK
Antworten