Sida 1 av 2
Nu ska vi C...
Postat: 25 november 2007, 14:31:59
av sodjan
Jag kan läsa och skriva C hjälpligt men är lite ringrostig på en del detaljer.
Jag skulle behöva lite hjälp med ett par detaljer i C, och antingen kan jag
ta det här, eller så kan jag köpa lite tid av någon (eller byta mot lite
prylar) om det skulle fungera bättre. Låt mig ta en detalj så att det framgår
vad det handlar om...
Jag har en funktion som ska anropas. Funktionen i sig kan jag inte påverka,
och jag har inte studerat hur den ser ut internt, det finns dock källkod i C
till allt, om det är intressant.
Funktionen har bl.a två parametrar som är "struct".
Den ena av dessa struct's har i sig structs som members i två undernivåer.
Nu är frågan, räcker det med att definiera en "struct variabel" i min egen kod
för den högsta struct nivån ?
kompileringen verkar gå OK (Det blir några fel men de ser inte ut att vara
rellaterade till detta), men vid körning som smäller det av någonstans
i anropet av denna funktion. Man får en call-stack-dump så man ser
exakt på vilken källkodsrad och i vilken under-funktion som det stannar,
men jag har inte fördjupat mig i det.
Just nu gäller det bara vad man måste definiera i min C kod för att struct'arna
ska fungera på rätt sätt.
Parametern med flernivå structen är ut-parametrer från funtionen och den
ska fylla i den, är meningen...
Men, som sagt, frågan är om det fungerar så här på forumet, eller om det
finns någon som mot ersättning skulle vilka lägga ett par timmer på detta...
Postat: 25 november 2007, 14:52:49
av Micke_s
Någonstans måste datan lagras, så du måste se till att definera det innan funktionen anropas..
Postat: 25 november 2007, 15:05:47
av rehnmaak
Kan du lägga upp funktionsdeklarationen?
EDIT: Den ligger väl i någon .h fil någonstans...
Postat: 25 november 2007, 15:07:08
av TomasL
Hmm, innan funktionen anropas måste bägge parametrarna vara definerade, dvs:
Kod: Markera allt
aStruct PAR1;
bStruct PAR2;
func( *PAR1, *PAR2){
.....
}
Sedan måste du ju göra nånting med dina parametrar.
Eftersom du skickar en pekare till dina structar,
ungefär så här:
Kod: Markera allt
PAR1.MEMBER1.MEMBER11->MEMBER111= nånting;
Osv.
Vore lättare om man fick se koden
Postat: 25 november 2007, 15:08:05
av SvenW
Det finns inga skydd i C, så det mesta går igenom kompilatorn. Men för att det inte ska 'segfaulta' så måste kompilatorn veta hur minnesarean (structen) skall tolkas. Normalt finns 'strukten' deklarerad i en headerfil, men om den saknas där får man skriva den själv på egen risk. Extra farligt blir det om den dessutom innehåller pekare, för hur de används vet inte alltid kompilatorn.
Om koden inte är alltför stor, eller hemlig, kanske du kan skicka ett exempel, hit eller via email,så skall jag ge konkreta råd. Helt fritt!
Postat: 25 november 2007, 17:52:25
av speakman
Du skulle ju köra Python till det där sa jag...

Men f.ö. tycker jag du kan ta allt här, och publicera gott om källkod så blir det enklare att supporta.
Postat: 25 november 2007, 18:27:39
av sodjan
OK.
Jag ska göra utdrag ur .h filerna av rellevanta delar.
(Hela .h filerna är ca 200 kB text och det blir nog lite mycket...)
Återkommer med det. Först bara några kommenterar till svaren så långt...
> aStruct PAR1;
> bStruct PAR2;
>
> func( *PAR1, *PAR2){
>
Så ser det i princip ut.
PAR1 är indata och PAR2 är utdata från func().
PAR1 är en struct i en nivå.
PAR2 är en struct som i sig innehåller struct's (i två nivåer).
Min huvudfråga var att man alltså inte behöver definiera
cStruct, dStruct o.s.v (som ingår i bStruct) i själva C koden
tillsammans med aStruct och bStruct ovan. Det åker så att säga
med på köpet från h filerna. cStruct och dStruct finns naturligtsvis med
i h filerna...
> Du skulle ju köra Python till det där sa jag...

Jo, men jag vill även göra ett "proof-of-concept" med vanlig C
också för att ha något att jämföra med. Har du kört något
med SOAPpy (eller vad det nu hette) där in och ut parametrar
är structs ? Jag såg bara exempel med "vanliga" int's eller strings.
> Men för att det inte ska 'segfaulta'
Hm, jag får en ACCVIO (Access Violation) från en underfunktion till
"func" ovan. Ska spåra vad den gör. ACCVIO betyder i princip samma sak.
Programmet försöker komma åt adresser som den inte får komma åt...
Måste lägga till någon switch till kompilatorn så att jag får ut allt i LST filen.
Call-stacken visas i alla fall :
Kod: Markera allt
%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=FFFFFFFFFFFFFFFF, PC=000000000007275C, PS=0000001B
%TRACE-F-TRACEBACK, symbolic stack dump follows
image module routine line rel PC abs PC
GETSELLERITEMS 0 000000000007275C 000000000007275C
GETSELLERITEMS SOAPC soap_out__ns1__GetSellerItems
26488 0000000000014298 0000000000044A18
GETSELLERITEMS SOAPC soap_out___ns2__GetSellerItems
24169 0000000000009F80 000000000003A700
GETSELLERITEMS SOAPC soap_put___ns2__GetSellerItems
24162 0000000000000000 0000000000000000
GETSELLERITEMS SOAPCLIENT soap_call___ns2__GetSellerItems
21261 00000000000005BC 00000000000570FC
GETSELLERITEMS GETSELLERITEMS main 42628 00000000000006D4 00000000000306D4
GETSELLERITEMS GETSELLERITEMS __main
42538 000000000000026C 000000000003026C
0 FFFFFFFF8032FF94 FFFFFFFF8032FF94
$
Så det gäller att kolla vad som ligger på rad 26488 i "soap_out__ns1__GetSellerItems"...
Postat: 25 november 2007, 19:01:59
av TomasL
Det beror på hur structen är gjord.
Om du har en
eller en
Kod: Markera allt
typedef STRUCT1{
......................
} par1;
är en viss skillnad.
I första versionen deklarerar du en variabel med strukturen
I andra versionen skapar du en ny typ-defintion, som du sedan kan använda var som helst för att deklarera variabler.
oavsett vilket, normalt behöver du bara deklarera din variabel en gång i början av koden, till exempel i .h fil som du inkluderar i början.
sedan beror det på hur koden ser ut om du behöver deklarera en lokal variabel för structen.
oavsett hur många inkappslade structar du har, kommer du alltid åt dem med
I ovanstående exempel är det en struct kapslad i 4 nivåer, sedan kan man förenkla återkomsten med en union om man vill.
Postat: 25 november 2007, 19:08:40
av SvenW
sodjan:
Innan du lägger ner mer jobb med att klippa hit kod, ser du felet i följande exempel?
void
foo_bar (void)
{
char *s;
sprintf(s, "%s\n", "Hello World");
printf(s);
}
Jag menar, det är en vanlig feltyp. Tror du det kan vara något dylikt?
Postat: 25 november 2007, 23:04:27
av sodjan
Så, jag tror att jag har "pin-pointat" felet lite bättre.
Här kommer rellevanta delar som berör just detta.
Det jag är osäker på är t.ex mktime(), och naturligtsvis varför
jag får "CVTDIFTYPES" varningen nedan. Jag skulle vilja
fokusera på att få bort kompilatorvarningen först, tror jag...
Jag kan "hacka runt" och prova olika ändringar, men om någon
ser något uppenbart fel/konstigt så vore det jättebra...
Jag har kollat vad som fanns på rad 26488 i "soap_out__ns1__GetSellerItems" (d.v.s där ACCVIO inträffar):
Kod: Markera allt
1 26488 soap_out_PointerTotime(soap, "ns1:minEndDate", -1, &a->minEndDate, "");
Denna rad skulle kunna hänga ihop med en kompilatorvarning som
jag inte lyckades få bort :
Kod: Markera allt
gsi_params.minEndDate = mktime(&mindate_tm);
..^
%CC-W-CVTDIFTYPES, In this statement, "mktime(...)" of type "unsigned long", is being converted to "pointer to unsigned long".
at line number 210 in file TRADERA_ROOT:<GETSELLERITEMS>GETSELLERITEMS.C;73
Kan denna varning göra att mktime() och/eller tilldelningen inte fungerar som förväntat ?
Och i så fall, hur får man bort varningen ?
gsi_params är definierad med :
_ns1__GetSellerItems är definierad (i en h fil) som :
Kod: Markera allt
struct _ns1__GetSellerItems
{
int userId;
int categoryId;
int filterType;
time_t *minEndDate;
time_t *maxEndDate;
};
mindate_tm är definieras genom :
tm är den vanliga tm struct'en från time.h:
Kod: Markera allt
struct tm {
int tm_sec; /* seconds after the minute [0, 61] */
int tm_min; /* minutes after the hour [0, 59] */
int tm_hour; /* hours since midnight [0, 23] */
int tm_mday; /* day of the month [1, 31] */
int tm_mon; /* months since January [0, 11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0, 6] */
int tm_yday; /* days since January 1 [0, 365] */
int tm_isdst; /* Daylight Saving Time flag */
};
jag misstänker att felet antingen har med den där varningen att göra
eller att det ligger i hur jag sätter up mindate_tm strukturen:
Kod: Markera allt
mindate_tm.tm_sec = 0;
mindate_tm.tm_min = 0;
mindate_tm.tm_hour = 0;
mindate_tm.tm_mday = atoi(tradapi_minday);
mindate_tm.tm_mon = atoi(tradapi_minmon);
mindate_tm.tm_year = atoi(tradapi_minyear);
De tre variablerna är char variabler:
Kod: Markera allt
char tradapi_minyear[4];
char tradapi_minmon[2];
char tradapi_minday[2];
och innehåller rätt strängar. Det är kollat.
Postat: 25 november 2007, 23:29:14
av rehnmaak
Jag gissar att problemet är att minEndDate ska vara en pekare till time_t. Du tilldelar den medlemen med *värdet* time_t. När den försöker adressera minEndDate så bombar det...
Kod: Markera allt
gsi_params.minEndDate = mktime(&mindate_tm);
Om du istället ger den en pekare så kanske den blir nöjd.
Kod: Markera allt
time_t putte;
putte = mktime(&mindate_tm);
gsi_params.minEndDate = &putte;
Postat: 26 november 2007, 08:59:59
av speakman
Kom då ihåg att variablen "putte" blir out-of-scope när du returnerar från funktionen, så antagligen blir du tvungen att göra en malloc där istället för den automatiskta variabeldefineringen.
Ang. Python så tycker jag det är lite märkligt om dom gör en SOAP-implementation som inte klarar de mer fundamentala delarna, men jag har som sagt ingen egen erfarenhet av det tyvärr.
Postat: 26 november 2007, 10:24:52
av SvenW
sodjan:
Jo, jag tror att din misstanke är korrekt.
struct _ns1__GetSellerItems
{
int userId;
int categoryId;
int filterType;
time_t *minEndDate;
time_t *maxEndDate;
};
%CC-W-CVTDIFTYPES, In this statement, "mktime(...)" of type "unsigned long", is being converted to "pointer to unsigned long".
at line number 210 in file TRADERA_ROOT:<GETSELLERITEMS>GETSELLERITEMS.C;73
Varningsutskriften säger "is being converted to", och det betyder att du får en pekare
som leder till underjordens demoner. Du skall skriva:
*gsi_params.minEndDate = mktime(&mindate_tm);
och pekaren 'time_t *minEndDate' skall vara giltig, dvs peka på en adress som finns.
Och som speakman påpekar, den skall vara 'in scope' i den funktion där den används.
Postat: 26 november 2007, 10:54:27
av speakman
Det beror ju en hel del på vad man förväntas få i *minEndDate.
Ska den peka på en time_t-variabel med validt data, eller pekar den redan på en time_t-variabel som *ska fyllas* med validt data.
Postat: 26 november 2007, 11:02:11
av maha
"validt data", många svengelska uttryck har jag sett (och använder) men det där var det kulaste på länge...
