Thread: call to library gives unexpected results

  1. #1
    Registered User
    Join Date
    Jul 2011
    Posts
    99

    call to library gives unexpected results

    I have compiled a shared library and a testprogram for that library. Originally, the testprogram was the main() of the library, but since I want to separate them, I divided into a library and a testprogram. This is not the only reason however, in the final program, the library will actually be a library and function as such.

    When I run the program with the main() in the original file, all works well. If I separate stuff into the files matchingEngine.c, matchingEngine.h and testMatchingEngine.c, and I compile and run testMatchingEngine (which contains the original main() ), I get unexpected results. It is rather a lengthy post, but it will turn out to be needed anyway, so I will just get right at it. Below you will find:
    - the sourcecode of the original file
    - my command line mingw (windows gcc clone) compiler commands
    - the output of the original program
    - the sourcecode of the original file split up in matchingEngine.c, matchingEngine.h and testMatchingEngine.c
    - my command line mingw (windows gcc clone) compiler commands
    - output of the modified program

    Once again, I suspect the mistake is somewhere in the headers, but I put the code here because in the end everybody asks for it anyway. So before you start digging in: this is probably about separating a program into a library and a working program in a wrong way (before you start didding into the code right away)

    QUESTION: Why do the results of the modified program differ from the original program?


    SOURCE CODE ORIGINAL PROGRAM
    Code:
    matchingEngineOriginal.c
    -----------------------
    #include <stdio.h>
    #include <stdlib.h>
    
    struct order {
    	char dir;
    	float price;
    	int actualSize;
    	int filledSize;
    	char instr[5];
    };
    
    struct bookOrder {
    	struct bookOrder *next;
    	struct order *order;
    };
    
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    
    void printBook(char *message) {
    
    	struct bookOrder *sellWalker = sellBook;
    	struct bookOrder *buyWalker = buyBook;
    
    	printf("\n%s\n", message);
    	
    	printf("--------BUY---------|---------SELL---------\n");
    	while ((buyWalker != NULL) || (sellWalker !=NULL)){
    		
    		//stuff to help with printing in the right place
    		char *marker = "";
    		int margin = 4;
    		
    		if (buyWalker != NULL) {
    			printf("%10i %10.3f",(buyWalker->order)->actualSize, (buyWalker->order)->price);
    			buyWalker = buyWalker->next;
    		}
    		else
    			margin = 15;
    		if (sellWalker != NULL){
    			printf("%*s %7.3f %5i",margin, marker, (sellWalker->order)->price, (sellWalker->order)->actualSize);
    			sellWalker = sellWalker->next;
    		}
    		printf("\n");
    	}
    	printf("------------------------------------\n");
    }
    
    void addBuyOrder(struct bookOrder **book, struct order buyOrder) {
    	
    	struct bookOrder *walker = *book;
    	struct bookOrder *follower = *book;
    	struct bookOrder *newBook = malloc(sizeof(**book));
    	struct order *newOrder = malloc(sizeof(buyOrder));
    	
    	//make new node
    	newOrder->price = buyOrder.price;
    	newOrder->actualSize = buyOrder.actualSize;	
    	newBook->order = newOrder;
    	newBook->next = NULL;
    	
    	if (*book == NULL) {
    		*book = newBook;
    	}
    	else {
    		//go on till walker is at first price that is lower
    		while ((walker->order->price >= newOrder->price) && (walker->next != NULL)) {
    			follower = walker;
    			walker = walker->next;
    		}
    		//insert before walker if walkerprice is lower
    		if (walker->order->price < newOrder->price) {
    		//insert before walker
    			//we are placing record as the first record
    			if (walker == follower) {
    				newBook->next = *book;
    				*book = newBook;
    			}
    			//more records
    			else {
    				follower->next = newBook;
    				newBook->next = walker;
    			}
    		}
    		else {
    			//insert after walker
    			follower = walker->next;
    			walker->next = newBook;
    			newBook->next = follower;
    		}	
    	}	
    }
    
    void addSellOrder(struct bookOrder **book, struct order sellOrder) {
    	
    	struct bookOrder *walker = *book;
    	struct bookOrder *follower = *book;
    	struct bookOrder *newBook = malloc(sizeof(**book));
    	struct order *newOrder = malloc(sizeof(sellOrder));
    	
    	//make new node
    	newOrder->price = sellOrder.price;
    	newOrder->actualSize = sellOrder.actualSize;	
    	newBook->order = newOrder;
    	newBook->next = NULL;
    	
    	if (*book == NULL) {
    		*book = newBook;
    	}
    	else {
    		while ((walker->order->price <= sellOrder.price) && (walker->next != NULL)) {
    			follower = walker;
    			walker = walker->next;
    		}
    		if (walker->order->price > sellOrder.price)
    			//insert before walker
    			if (walker == follower) {
    				newBook->next = *book;
    				*book = newBook;
    			}
    			else {
    				follower->next = newBook;
    				newBook->next = walker;
    			}
    		else {
    			//insert after walker
    			follower = walker->next;
    			walker->next = newBook;
    			newBook->next = follower;
    		}	
    	}	
    }
    
    
    //deletes the first row in a book
    void deleteOrder(struct bookOrder **orderBook) {
    
    	if (*orderBook != NULL) {
    		struct bookOrder *tmp = *orderBook;
    		*orderBook = (*orderBook)->next;
    		tmp->next = NULL;
    		free(tmp);
    	}
    }
    
    //returns number of matches
    int matchBuyOrder(struct bookOrder **sellOrderBook, struct order buyOrder, int numbOfMatches) {
    
    	int noMatches = numbOfMatches;
    	int size;
    	if (*sellOrderBook == NULL)
    		return noMatches;
    	
    	if (buyOrder.price >= (*sellOrderBook)->order->price) {
    		size = buyOrder.actualSize - (*sellOrderBook)->order->actualSize;
    		++noMatches;
    		if (size == 0) {
    //			sendReport(createTransactionReport());
    			deleteOrder(sellOrderBook);
    		}
    		else if(size > 0) {
    //			sendReport(createTransactionReport());
    			buyOrder.filledSize = buyOrder.actualSize - size;
    			buyOrder.actualSize = size;
    			deleteOrder(sellOrderBook);
    			matchBuyOrder(sellOrderBook, buyOrder, noMatches);
    		}
    		else {
    //			sendReport(createTransactionReport());
    			(*sellOrderBook)->order->filledSize += buyOrder.actualSize;
    			(*sellOrderBook)->order->actualSize = -size;
    		}
    	}
    	else
    		addBuyOrder(&buyBook, buyOrder);
    	return noMatches;
    }
    
    //returns number of matches
    int matchSellOrder(struct bookOrder **buyOrderBook, struct order sellOrder, int numbOfMatches) {
    
    	int noMatches = numbOfMatches;
    	int size;
    	if (*buyOrderBook == NULL) {
    		addSellOrder(&sellBook, sellOrder);
    		return noMatches;
    	}
    	
    	//
    	if (sellOrder.price <= (*buyOrderBook)->order->price) {
    		size = sellOrder.actualSize - (*buyOrderBook)->order->actualSize;
    		++noMatches;
    		if (size == 0) {
    //			sendReport(createTransactionReport());
    			deleteOrder(buyOrderBook);
    		}
    		else if(size > 0) {
    //			sendReport(createTransactionReport());
    			sellOrder.filledSize = sellOrder.actualSize - size;
    			sellOrder.actualSize = size;
    			deleteOrder(buyOrderBook);
    			matchSellOrder(buyOrderBook, sellOrder, noMatches);
    		}
    		else {
    //			sendReport(createTransactionReport());
    			(*buyOrderBook)->order->filledSize += sellOrder.actualSize;
    			(*buyOrderBook)->order->actualSize = -size;
    		}
    	}
    	else {
    	printf("here?\n");
    		addSellOrder(&sellBook, sellOrder);
    	}
    	return noMatches;
    }
    
    
    
    int main(void) {
    
    	//insert order and print
    	struct order inpOrder;
    	inpOrder.price = 29.88888;
    	inpOrder.actualSize = 600;
    	addSellOrder(&sellBook, inpOrder);
    
    	inpOrder.price = 30;
    	inpOrder.actualSize = 600;
    	addSellOrder(&sellBook, inpOrder);
    
    	inpOrder.price = 100;
    	inpOrder.actualSize = 600;
    	addSellOrder(&sellBook, inpOrder);
    
    	printBook("Initial");
    	
    	
    	inpOrder.price = 300;
    	inpOrder.actualSize = 600;
    	addBuyOrder(&buyBook, inpOrder);
    	printBook("Initial");
    
    	inpOrder.price = 300;
    	inpOrder.actualSize = 600;
    	addBuyOrder(&buyBook, inpOrder);
    	
    	
    	
    	
    	//insert order and print
    	inpOrder.price = 67;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//insert order and print
    	inpOrder.price = 57;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//insert order and print
    	inpOrder.price = 20;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//insert order and print
    	inpOrder.price = 67;
    	inpOrder.actualSize = 380;
    	addSellOrder(&sellBook, inpOrder);
    	
    	//insert order and print
    	inpOrder.price = 59;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    	
    	//insert order and print
    	inpOrder.price = 10;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//buyorders
    	inpOrder.price = 10;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 90;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 45.9;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 100.8;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 8.0331;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    	
    	inpOrder.price = 600;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    	
    	inpOrder.price = 90;
    	inpOrder.actualSize = 100;
    	addBuyOrder(&buyBook, inpOrder);
    	printBook("Initial");
    
    	//match order and print
    getchar();
    	inpOrder.price = 58;
    	inpOrder.actualSize = 200;
    	matchBuyOrder(&sellBook, inpOrder, 0);
    	printBook("match  buy 200@58");
    	
    
    	//match order and print
    getchar();
    	inpOrder.price = 69;
    	inpOrder.actualSize = 100000;
    	matchBuyOrder(&sellBook, inpOrder, 0);
    	printBook("match  buy 100000@69");
    
    	//match order and print
    getchar();
    	inpOrder.price = 100;
    	inpOrder.actualSize = 440;
    	matchSellOrder(&buyBook, inpOrder, 0);
    	printBook("match  sell 440@100");
    
    	//match order and print
    getchar();
    	inpOrder.price = 8;
    	inpOrder.actualSize = 100000;
    	matchSellOrder(&buyBook, inpOrder, 0);
    	printBook("match  sell 100000@8");
    
    	return 0;
    }
    COMPILER COMMANDS ORIGINAL PROGRAM
    gcc ..\source\matchingEngineOriginal.c

    OUTPUT ORIGINAL PROGRAM

    Initial
    --------BUY---------|---------SELL---------
    29.889 600
    30.000 600
    100.000 600
    ------------------------------------

    Initial
    --------BUY---------|---------SELL---------
    600 300.000 29.889 600
    30.000 600
    100.000 600
    ------------------------------------

    Initial
    --------BUY---------|---------SELL---------
    340 600.000 10.000 340
    600 300.000 20.000 340
    600 300.000 29.889 600
    340 100.800 30.000 600
    340 90.000 57.000 340
    100 90.000 59.000 340
    340 45.900 67.000 340
    340 10.000 67.000 380
    340 8.033 100.000 600
    ------------------------------------

    match buy 200@58
    --------BUY---------|---------SELL---------
    340 600.000 10.000 140
    600 300.000 20.000 340
    600 300.000 29.889 600
    340 100.800 30.000 600
    340 90.000 57.000 340
    100 90.000 59.000 340
    340 45.900 67.000 340
    340 10.000 67.000 380
    340 8.033 100.000 600
    ------------------------------------

    match buy 100000@69
    --------BUY---------|---------SELL---------
    340 600.000 100.000 600
    600 300.000
    600 300.000
    340 100.800
    340 90.000
    100 90.000
    96920 69.000
    340 45.900
    340 10.000
    340 8.033
    ------------------------------------

    match sell 440@100
    --------BUY---------|---------SELL---------
    500 300.000 100.000 600
    600 300.000
    340 100.800
    340 90.000
    100 90.000
    96920 69.000
    340 45.900
    340 10.000
    340 8.033
    ------------------------------------

    match sell 100000@8
    --------BUY---------|---------SELL---------
    8.000 180
    100.000 600
    ------------------------------------


    SOURCE CODE MODIFIED PROGRAM
    Code:
    matchingEngine.c
    -----------------
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "matchingEngine.h"
    /*
    struct order {
    	char dir;
    	float price;
    	int actualSize;
    	int filledSize;
    	char instr[5];
    };
    
    struct bookOrder {
    	struct bookOrder *next;
    	struct order *order;
    };
    
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    */
    
    void printBook(char *message) {
    
    	struct bookOrder *sellWalker = sellBook;
    	struct bookOrder *buyWalker = buyBook;
    
    	printf("\n%s\n", message);
    	
    	printf("--------BUY---------|---------SELL---------\n");
    	while ((buyWalker != NULL) || (sellWalker !=NULL)){
    		
    		//stuff to help with printing in the right place
    		char *marker = "";
    		int margin = 4;
    		
    		if (buyWalker != NULL) {
    			printf("%10i %10.3f",(buyWalker->order)->actualSize, (buyWalker->order)->price);
    			buyWalker = buyWalker->next;
    		}
    		else
    			margin = 15;
    		if (sellWalker != NULL){
    			printf("%*s %7.3f %5i",margin, marker, (sellWalker->order)->price, (sellWalker->order)->actualSize);
    			sellWalker = sellWalker->next;
    		}
    		printf("\n");
    	}
    	printf("------------------------------------\n");
    }
    
    void addBuyOrder(struct bookOrder **book, struct order buyOrder) {
    	
    	struct bookOrder *walker = *book;
    	struct bookOrder *follower = *book;
    	struct bookOrder *newBook = malloc(sizeof(**book));
    	struct order *newOrder = malloc(sizeof(buyOrder));
    	
    	//make new node
    	newOrder->price = buyOrder.price;
    	newOrder->actualSize = buyOrder.actualSize;	
    	newBook->order = newOrder;
    	newBook->next = NULL;
    	
    	if (*book == NULL) {
    		*book = newBook;
    	}
    	else {
    		//go on till walker is at first price that is lower
    		while ((walker->order->price >= newOrder->price) && (walker->next != NULL)) {
    			follower = walker;
    			walker = walker->next;
    		}
    		//insert before walker if walkerprice is lower
    		if (walker->order->price < newOrder->price) {
    		//insert before walker
    			//we are placing record as the first record
    			if (walker == follower) {
    				newBook->next = *book;
    				*book = newBook;
    			}
    			//more records
    			else {
    				follower->next = newBook;
    				newBook->next = walker;
    			}
    		}
    		else {
    			//insert after walker
    			follower = walker->next;
    			walker->next = newBook;
    			newBook->next = follower;
    		}	
    	}	
    }
    
    void addSellOrder(struct bookOrder **book, struct order sellOrder) {
    	
    	struct bookOrder *walker = *book;
    	struct bookOrder *follower = *book;
    	struct bookOrder *newBook = malloc(sizeof(**book));
    	struct order *newOrder = malloc(sizeof(sellOrder));
    	
    	//make new node
    	newOrder->price = sellOrder.price;
    	newOrder->actualSize = sellOrder.actualSize;	
    	newBook->order = newOrder;
    	newBook->next = NULL;
    	
    	if (*book == NULL) {
    		*book = newBook;
    	}
    	else {
    		while ((walker->order->price <= sellOrder.price) && (walker->next != NULL)) {
    			follower = walker;
    			walker = walker->next;
    		}
    		if (walker->order->price > sellOrder.price)
    			//insert before walker
    			if (walker == follower) {
    				newBook->next = *book;
    				*book = newBook;
    			}
    			else {
    				follower->next = newBook;
    				newBook->next = walker;
    			}
    		else {
    			//insert after walker
    			follower = walker->next;
    			walker->next = newBook;
    			newBook->next = follower;
    		}	
    	}	
    }
    
    
    //deletes the first row in a book
    void deleteOrder(struct bookOrder **orderBook) {
    
    	if (*orderBook != NULL) {
    		struct bookOrder *tmp = *orderBook;
    		*orderBook = (*orderBook)->next;
    		tmp->next = NULL;
    		free(tmp);
    	}
    }
    
    //returns number of matches
    int matchBuyOrder(struct bookOrder **sellOrderBook, struct order buyOrder, int numbOfMatches) {
    
    	int noMatches = numbOfMatches;
    	int size;
    	if (*sellOrderBook == NULL)
    		return noMatches;
    	
    	if (buyOrder.price >= (*sellOrderBook)->order->price) {
    		size = buyOrder.actualSize - (*sellOrderBook)->order->actualSize;
    		++noMatches;
    		if (size == 0) {
    //			sendReport(createTransactionReport());
    			deleteOrder(sellOrderBook);
    		}
    		else if(size > 0) {
    //			sendReport(createTransactionReport());
    			buyOrder.filledSize = buyOrder.actualSize - size;
    			buyOrder.actualSize = size;
    			deleteOrder(sellOrderBook);
    			matchBuyOrder(sellOrderBook, buyOrder, noMatches);
    		}
    		else {
    //			sendReport(createTransactionReport());
    			(*sellOrderBook)->order->filledSize += buyOrder.actualSize;
    			(*sellOrderBook)->order->actualSize = -size;
    		}
    	}
    	else
    		addBuyOrder(&buyBook, buyOrder);
    	return noMatches;
    }
    
    //returns number of matches
    int matchSellOrder(struct bookOrder **buyOrderBook, struct order sellOrder, int numbOfMatches) {
    
    	int noMatches = numbOfMatches;
    	int size;
    	if (*buyOrderBook == NULL) {
    		addSellOrder(&sellBook, sellOrder);
    		return noMatches;
    	}
    	
    	//
    	if (sellOrder.price <= (*buyOrderBook)->order->price) {
    		size = sellOrder.actualSize - (*buyOrderBook)->order->actualSize;
    		++noMatches;
    		if (size == 0) {
    //			sendReport(createTransactionReport());
    			deleteOrder(buyOrderBook);
    		}
    		else if(size > 0) {
    //			sendReport(createTransactionReport());
    			sellOrder.filledSize = sellOrder.actualSize - size;
    			sellOrder.actualSize = size;
    			deleteOrder(buyOrderBook);
    			matchSellOrder(buyOrderBook, sellOrder, noMatches);
    		}
    		else {
    //			sendReport(createTransactionReport());
    			(*buyOrderBook)->order->filledSize += sellOrder.actualSize;
    			(*buyOrderBook)->order->actualSize = -size;
    		}
    	}
    	else {
    	printf("here?\n");
    		addSellOrder(&sellBook, sellOrder);
    	}
    	return noMatches;
    }
    
    
    
    matchingEngine.h
    -----------------
    
    #include <stdio.h>
    #include <stdlib.h>
    
    struct order {
    	char dir;
    	float price;
    	int actualSize;
    	int filledSize;
    	char instr[5];
    };
    
    struct bookOrder {
    	struct bookOrder *next;
    	struct order *order;
    };
    
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    
    void printBook(char *message);
    
    void addBuyOrder(struct bookOrder **book, struct order buyOrder);
    
    void addSellOrder(struct bookOrder **book, struct order sellOrder);
    
    void deleteOrder(struct bookOrder **orderBook);
    
    //returns number of matches
    int matchBuyOrder(struct bookOrder **sellOrderBook, struct order buyOrder, int numbOfMatches);
    
    //returns number of matches
    int matchSellOrder(struct bookOrder **buyOrderBook, struct order sellOrder, int numbOfMatches); 
    
    
    testMatchingEngine.c
    --------------------
    #include <stdio.h>
    #include <stdlib.h>
    #include "matchingEngine.h"
    
    
    int main(void) {
    
    	//insert order and print
    	struct order inpOrder;
    	inpOrder.price = 29.88888;
    	inpOrder.actualSize = 600;
    	addSellOrder(&sellBook, inpOrder);
    
    	printBook("Initial");
    
    	inpOrder.price = 30;
    	inpOrder.actualSize = 600;
    	addSellOrder(&sellBook, inpOrder);
    
    	inpOrder.price = 100;
    	inpOrder.actualSize = 600;
    	addSellOrder(&sellBook, inpOrder);
    
    	printBook("Initial");
    	
    	inpOrder.price = 300;
    	inpOrder.actualSize = 600;
    	addBuyOrder(&buyBook, inpOrder);
    	printBook("Initial");
    
    	inpOrder.price = 300;
    	inpOrder.actualSize = 600;
    	addBuyOrder(&buyBook, inpOrder);
    	
    	//insert order and print
    	inpOrder.price = 67;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//insert order and print
    	inpOrder.price = 57;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//insert order and print
    	inpOrder.price = 20;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//insert order and print
    	inpOrder.price = 67;
    	inpOrder.actualSize = 380;
    	addSellOrder(&sellBook, inpOrder);
    	
    	//insert order and print
    	inpOrder.price = 59;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    	
    	//insert order and print
    	inpOrder.price = 10;
    	inpOrder.actualSize = 340;
    	addSellOrder(&sellBook, inpOrder);
    
    	//buyorders
    	inpOrder.price = 10;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 90;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 45.9;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 100.8;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    
    	inpOrder.price = 8.0331;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    	
    	inpOrder.price = 600;
    	inpOrder.actualSize = 340;
    	addBuyOrder(&buyBook, inpOrder);
    	
    	inpOrder.price = 90;
    	inpOrder.actualSize = 100;
    	addBuyOrder(&buyBook, inpOrder);
    	printBook("Initial");
    
    	//match order and print
    getchar();
    	inpOrder.price = 58;
    	inpOrder.actualSize = 200;
    	matchBuyOrder(&sellBook, inpOrder, 0);
    	printBook("match  buy 200@58");
    	
    
    	//match order and print
    getchar();
    	inpOrder.price = 69;
    	inpOrder.actualSize = 100000;
    	matchBuyOrder(&sellBook, inpOrder, 0);
    	printBook("match  buy 100000@69");
    
    	//match order and print
    getchar();
    	inpOrder.price = 100;
    	inpOrder.actualSize = 440;
    	matchSellOrder(&buyBook, inpOrder, 0);
    	printBook("match  sell 440@100");
    
    	//match order and print
    getchar();
    	inpOrder.price = 8;
    	inpOrder.actualSize = 100000;
    	matchSellOrder(&buyBook, inpOrder, 0);
    	printBook("match  sell 100000@8");
    
    	return 0;
    }
    COMPILER COMMANDS MODIFIED PROGRAM
    gcc -c -fpic ..\source\matchingEngine.c
    gcc -shared -o matchingEngine.so matchingEngine.o
    gcc -I..\source -L..\bin -o testMatchingEngine ..\source\testMatchingEngine.c matchingEngine.so


    OUTPUT MODIFIED PROGRAM

    Initial
    --------BUY---------|---------SELL---------
    ------------------------------------

    Initial
    --------BUY---------|---------SELL---------
    ------------------------------------

    Initial
    --------BUY---------|---------SELL---------
    ------------------------------------

    Initial
    --------BUY---------|---------SELL---------
    ------------------------------------

    match buy 200@58
    --------BUY---------|---------SELL---------
    ------------------------------------

    match buy 100000@69
    --------BUY---------|---------SELL---------
    96920 69.000
    ------------------------------------

    match sell 440@100
    --------BUY---------|---------SELL---------
    96920 69.000
    ------------------------------------

    match sell 100000@8
    --------BUY---------|---------SELL---------
    96920 69.000 8.000 97100
    ------------------------------------
    Last edited by django; 08-25-2011 at 07:28 AM.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    NO CODE IN .H FILES! Remember that .h files are quite simply just pasted into the top of all your .c files, so anything that appears there will appear in each of your .c files separately.

    You can do "extern struct bookOrder *sellBook;" in your .h file, and then actually define the variable in one actual .c file. As it stands each file gets its own copy of each of your "global" variables.

    I know you asked not to hear it, but I'm typing it anyway: Also note that you have completely destroyed your functions by your use of global variables. Your function that should walk a list (that's "a" list, as in any list) now only walks that one particular list, and is therefore basically unusable.

  3. #3
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Quote Originally Posted by tabstop View Post
    NO CODE IN .H FILES! Remember that .h files are quite simply just pasted into the top of all your .c files, so anything that appears there will appear in each of your .c files separately.
    Ok, I did not know about the header files being pasted into any sourcefile. That helps when thinking about it.
    I am aware of not doing code in a .h file, but do I, I have only variables in the .h file as far as I can see? (Maybe this relates to the use of EXTERN, see below.


    Quote Originally Posted by tabstop View Post
    You can do "extern struct bookOrder *sellBook;" in your .h file, and then actually define the variable in one actual .c file. As it stands each file gets its own copy of each of your "global" variables.
    You got me here, the 'extern' was a remainder of my previous stage: trying to compile and call a shared library. I copied it from an example as an attempt to get it to work without actually knowing what 'extern' does, I will read up on this.
    Quote Originally Posted by tabstop View Post
    I know you asked not to hear it, but I'm typing it anyway: Also note that you have completely destroyed your functions by your use of global variables. Your function that should walk a list (that's "a" list, as in any list) now only walks that one particular list, and is therefore basically unusable.
    Hm ok. I guess the design is faulty now, have to think this through. Thanks.

    I will correct the above, do you expect it to work or can you point out more precisely why I get different results for both programs?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The following is the code you have in your .h file:
    Code:
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    These need to be marked extern. The above code needs to appear in a .c file (but only one .c file).

    Making that fix, you'll probably get exactly what you expect. Your design issues (i.e. making your list-walker a list-walker and not a particular-list-walker) can be fixed at your leisure.

  5. #5
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Let me first understand what I am doing here, because I do not currently.
    Last edited by django; 08-25-2011 at 08:58 AM.

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by tabstop View Post
    The following is the code you have in your .h file:
    Code:
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    These need to be marked extern. The above code needs to appear in a .c file (but only one .c file).

    Making that fix, you'll probably get exactly what you expect. Your design issues (i.e. making your list-walker a list-walker and not a particular-list-walker) can be fixed at your leisure.
    What he is saying to to try putting the following in your header file
    Code:
    extern struct bookOrder *sellBook;
    extern struct bookOrder *buyBook;
    Then put in ONLY a single .c file.

    Code:
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    The use of the "extern" keyword says somewhere in the future the compiler will be told the location of that variable.

    Edit: To learn more on this subject look-up declare and definition as used in C/C++ programming.

    Tim S.
    Last edited by stahta01; 08-25-2011 at 09:45 AM. Reason: grammer

  7. #7
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Ok, it works no, once again, much obliged, also stahta for your illustration in a bit more detail, that did it.

    For anybody interested in the solution here is what I changed to make it work


    (1) I took the struct order and bookOrder out of the matchingEngine.c file
    (2) I took the variables struct bookOrder *sellBook and struct bookOrder *buyBook out of the header file.
    (3) I have added the lines:
    Code:
    extern struct bookOrder *sellBook;
    extern struct bookOrder *buyBook;
    to testMatchingEngine. This is needed because those struct's are defined in the header file.
    Note: you have to include the header file in the original file, so in this case matchingEngine.c between "" and not between <>. In the calling file testMatchingEngine you can use <>.

    REMAINING QUESTION: What I find strange is that I have to declare both structs in the header file. Since the header file is in the end derived from the original .c file, it would for me seem more logical to define it in the .c file and then call it for example in the header file with 'extern' that way the .c file remains independent. I tried this but it does not work. Can this be done somehow?
    Last edited by django; 08-25-2011 at 02:52 PM.

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    What you have in your "remaining question" should work, and what you say you have working shouldn't work. Your header file needs to have the extern lines in it. No other file should have extern lines in them. One file (your main .c file) should have the actual variables (without the extern) in them, at global scope (i.e., before main).

    (Also, because you are not the standards committee, you should not put your own header files inside the <angle brackets>, but only within "quotes".)

  9. #9
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Ok, strange because it works. So what you are saying is that I should define the structs in the .c file. Can you tell me how exactly I should put the extern structs declarations in the .h file?

    Btw in another thread you told me
    Quote Originally Posted by tabstop View Post
    If you intend to use the struct in various .c files, then you need the full definition of the struct in the .h file, not in the .c files.
    Does that change your mind somehow?
    Last edited by django; 08-25-2011 at 01:53 PM.

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    I think we're being sloppy about define and declare and things again.

    All your files need to know what a struct bookOrder actually and truly is. So your header files need to have
    Code:
    struct order {
    	char dir;
    	float price;
    	int actualSize;
    	int filledSize;
    	char instr[5];
    };
    
    struct bookOrder {
    	struct bookOrder *next;
    	struct order *order;
    };
    in it. Notice that this does not declare any variables, and that the last thing you want to do is declare any variables in the header file. Remember that this declaration of what a struct is needs to get pasted in to all the .c files so that they all agree on what this struct thing is.

    You need to define the variables
    Code:
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    once, because these variables should only exist one time (and everybody refers to the same one). Therefore you cannot put these in the header file, because things in the header file get pasted into all the .c files, and then each .c file would have their own sellBook and buyBook.

    You need to have
    Code:
    extern struct bookOrder *sellBook;
    extern struct bookOrder *buyBook;
    in the header file, so that the other code knows that variables of those names exist somewhere, but do not actually exist in that file.
    Last edited by tabstop; 08-25-2011 at 02:02 PM.

  11. #11
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    [QUOTE=tabstop;1048417]I think we're being sloppy about define and declare and things again.[QUOTE]
    Yes we were, but it's clear now, I defined the structs in the header file. What I find strange however, is that I cannot do this in the original c-file. If I want to make the original c-file into a library I have to take the struct's definitions out of it en move them to the header file, this I find kind of counter intuitive, which says probably a lot about what my intuition is worth in this matter.
    Quote Originally Posted by tabstop View Post
    You need to define the variables
    Code:
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    once, because these variables should only exist one time (and everybody refers to the same one). Therefore you cannot put these in the header file, because things in the header file get pasted into all the .c files, and then each .c file would have their own sellBook and buyBook.

    You need to have
    Code:
    extern struct bookOrder *sellBook;
    extern struct bookOrder *buyBook;
    in the header file, so that the other code knows that variables of those names exist somewhere, but do not actually exist in that file.
    I do not agree. I do not need those variables outside of the library. They are strictly accessed via the functions in the original .c file. But come to think of it, I think my whole use of the library is a bit weird. Usually, a library seems to me to be a set of functions that you want to use in different programs (e.g. a mathematical library). In my case, I have made a library because I wanted to test the different functions and not have it in the main of my original program. Maybe I should rethink this testing strategy.

  12. #12
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Quote Originally Posted by tabstop View Post
    I think we're being sloppy about define and declare and things again.
    Yes we were, but it's clear now, I defined the structs in the header file. What I find strange however, is that I cannot do this in the original c-file. If I want to make the original c-file into a library I have to take the struct's definitions out of it en move them to the header file, this I find kind of counter intuitive, which says probably a lot about what my intuition is worth in this matter.
    Quote Originally Posted by tabstop View Post
    You need to define the variables
    Code:
    struct bookOrder *sellBook;
    struct bookOrder *buyBook;
    once, because these variables should only exist one time (and everybody refers to the same one). Therefore you cannot put these in the header file, because things in the header file get pasted into all the .c files, and then each .c file would have their own sellBook and buyBook.

    You need to have
    Code:
    extern struct bookOrder *sellBook;
    extern struct bookOrder *buyBook;
    in the header file, so that the other code knows that variables of those names exist somewhere, but do not actually exist in that file.
    I do not agree. I do not need those variables outside of the library. They are strictly accessed via the functions in the original .c file. But come to think of it, I think my whole use of the library is a bit weird. Usually, a library seems to me to be a set of functions that you want to use in different programs (e.g. a mathematical library). In my case, I have made a library because I wanted to test the different functions and not have it in the main of my original program. Maybe I should rethink this testing strategy.

    BTW <> is reserved for includes of standard stuff, point taken.

    Anyhow, thanks again for your considerable effort, I can move ahead now. You guys really help me a lot!

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    This is where the "your functions are broken because of your use of global variables" comes in. There's also being generic, and being ultra generic which is really hard to do in C.

    Even still, you're being somewhat inconsistent here, which may be because you haven't stopped to think about what a .h file actually is. An .h file is everything that someone who uses your library needs to know. What this struct thing actually is is really really important for someone who wants to use your library, since that's the basic data type that they will be interfacing with your library -- it's the only data types your library really uses. People who use your library need to know your basic data types that you are defining: a struct to hold the information about a book (or "order", as you are calling it), and the struct that your list is built out of. The people who use your library really really need to know the names of your functions, and the parameters that go into them, because that's how they will actually use your library, by calling the functions.

    These global variables really should go away: they are the person-who-is-using-the-library's responsibility, to hold actual data. They don't really belong to the library at all. Your functions like addBuyOrder get it right -- they take a struct BookOrder** that represents the list we are working on. Your functions that don't take such a parameter are crippled, and to heal them you need to make them also take a struct BookOrder* or struct BookOrder** (if you know you won't affect the head of the list, the extra * isn't necessary) so that they can work on whatever list the person-who-is-using-the-library happens to have lying around and wants to have printed.

    If you wanted to go real generic, your list would look something like
    Code:
    struct list_item {
        void *data; //who knows what the list holds -- it's generic!
        struct list_item *next;
    };
    The list-walker-type functions would be more-or-less okay as they stand, as long as they don't need to know what kind of data data actually points to. (So you could walk the list, or insert at the end/beginning, but you couldn't insert in place because you don't know how to sort data.) If you want to see what that looks like in action, find some code that uses the standard library's qsort or bsearch.

  14. #14
    Registered User
    Join Date
    Jul 2011
    Posts
    99
    Thanks professor (no pun intended). Such background info about how to think about what a header file is, is really helpful: all you need to know in order to be able to use a library. The definitions of the structs make perfect sense then.
    I also approached it too much as an executable, a library gets disclosed via its header file isn't it? I mean, isn't the only way to use a .so library not via a header?

    Don't feel obliged to answer, I am already very happy with the stuff you taught me, thanks again, great place here.

  15. #15
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You don't "use" a library via a header. A header tells you what's available in the library. This is primarily constant definitions, struct declarations and function prototypes. This allows the compiler to make sure you are only referencing valid members of a struct, or that you are passing the right number and type of parameters to the library functions. It basically makes sure you're using everything correctly. The actual use of the library, that is the functions provided and calls to those functions, are handled by the linker and loader.

    If you remember from your other thread, the static libraries (libfoo.a) get compiled (during the linking stage) into your final executable. It's bigger, but it has no external needs. Everything is packaged up inside. The .so libraries are dynamically loaded. The linker phase of the compiler just puts a reference to the library in your program. When your program starts, the loader sees the reference and brings in a "copy" of the shared library for you to use. You can also, by using some functions, load and unload a .so library "on-demand", after your program has started running. This keeps your program size smaller, but means you rely on the user to have a copy of that shared library on their system.

    So, you can technically use a library (static or shared/.so) without using the header, but you're going to have tons of warnings and errors about missing prototypes, unknown variables, etc to deal with. It's doable, but very, very poor practice. Include the header so the compiler can keep you in check. Link in the library so you can actually use the functions.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Unexpected Results
    By Bailz in forum C Programming
    Replies: 5
    Last Post: 11-08-2006, 07:10 AM
  2. Unexpected results from function
    By ajdspud in forum C++ Programming
    Replies: 2
    Last Post: 11-27-2005, 04:19 PM
  3. Unexpected results
    By Syked4 in forum C Programming
    Replies: 2
    Last Post: 06-07-2005, 09:41 PM
  4. Unexpected results using argc / *argv[]
    By Morgan in forum C Programming
    Replies: 1
    Last Post: 09-11-2003, 01:38 AM
  5. C system call and library call
    By Coconut in forum C Programming
    Replies: 6
    Last Post: 08-22-2002, 11:20 AM