I am overlooking something obvious.

May 11, 2008
23,331
1,575
126
I hope someone can help me with this.


For some reason i do not understand, i cannot use the "CVI_FT_GetLibraryVersion" (or any other dll function for that matter)
outside the main function or the call back function. When i use the function inside winmain or the callback i do not get an exception. When i used in a function outside, i get an exception with the text :

project test raised exception class EAccesviolation with message 'Access violation at address 00090396' Read of address 00090396.



The weird part is that i get the exception only when selecting release mode in the compiler settings.

When i use the full debug mode i do not get any exception.

I am working with borland c++ builder 5.

I am still learning, if anybody has an idea i really appreciate it.


Here is a part of the code.


//**********************************************************************************************************************
//**********************************************************************************************************************
int Init_Window_Settings(HWND hwnd, int cxChar, int cyChar, int FTDI_enable)
{
unsigned long libraryversion;
unsigned char byte0,byte1,byte2;
static char sz_version_dll[40];

int i;
BOOL bresult;

HRESULT status;

// Write version of the FTD2XX.dll.
status = CVI_FT_GetLibraryVersion(&libraryversion);

/*if (status == FT_OK)
{
byte0 = libraryversion;
libraryversion = libraryversion >> 8;
byte1 = libraryversion;
libraryversion = libraryversion >> 8;
byte2 = libraryversion;

sprintf(sz_version_dll,"eEeSwitch ! dll ver. = 0%x.0%x.0%x",byte2,byte1,byte0);

}
else
{
sprintf(sz_version_dll,"eEeSwitch ! ");
MessageBox (NULL,"Failed to read FTDI dll version number !","eEeSwitch", MB_ICONERROR);
}

SetWindowText(hwnd,sz_version_dll);
*/


return 0;
}



//**********************************************************************************************************************
//**********************************************************************************************************************
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HMENU hMenu;
static int cxChar, cyChar ;
int i=1;
int status=0;
int Button;
BOOL bresult;

HINSTANCE hInstance ;
static HWND hwndButton[8];

static unsigned char led_state = 0;
unsigned char masked_led_state = 0;

static int options_flag=0; // Used for the options checkbox.

static unsigned char on_level_mask=0;
static unsigned char off_level_mask=0;

unsigned long libraryversion;
unsigned char byte0,byte1,byte2;
static char sz_version_dll[40];

// Get charachter dimensions.
cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;



switch (message)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;

case WM_DESTROY:
PostQuitMessage (0) ;
break;

case WM_CREATE:
//Draw 8 identical buttons.
for (i = 1 ; i < 9 ; i++)
hwndButton = CreateWindowEx (NULL,
"button",
" ",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
cxChar,
cyChar * (4 * i),
30 * cxChar,
9 * cyChar / 4,
hwnd,
(HMENU)i,
hInstance,
NULL);

//Draw a autocheckbox.
i=0;
hwndButton = CreateWindowEx (NULL,
"button",
"Options",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX | BS_LEFTTEXT,
cxChar,
35 * cyChar,
10 * cxChar,
9 * cyChar / 5,
hwnd,
(HMENU)i,
hInstance,
NULL);


// Get on level and off level invert masks bits.
on_level_mask = Get_On_Level_Cfg(&configdata);
off_level_mask = Get_Off_Level_Cfg(&configdata);

//Default states are initialized when program is started.
led_state = Get_Default_State_Cfg(&configdata);

Button = 1;
status = WriteButtonLabel(&configdata, hwndButton[1], Button, led_state);
Button = 2;
status = WriteButtonLabel(&configdata, hwndButton[2], Button, led_state);
Button = 3;
status = WriteButtonLabel(&configdata, hwndButton[3], Button, led_state);
Button = 4;
status = WriteButtonLabel(&configdata, hwndButton[4], Button, led_state);
Button = 5;
status = WriteButtonLabel(&configdata, hwndButton[5], Button, led_state);
Button = 6;
status = WriteButtonLabel(&configdata, hwndButton[6], Button, led_state);
Button = 7;
status = WriteButtonLabel(&configdata, hwndButton[7], Button, led_state);
Button = 8;
status = WriteButtonLabel(&configdata, hwndButton[8], Button, led_state);

Init_Window_Settings(hwnd, cxChar, cyChar, FTDI_enable_flag);

/* // Write version of the FTD2XX.dll.
status = CVI_FT_GetLibraryVersion(&libraryversion);

if (status == FT_OK)
{
byte0 = libraryversion;
libraryversion = libraryversion >> 8;
byte1 = libraryversion;
libraryversion = libraryversion >> 8;
byte2 = libraryversion;

sprintf(sz_version_dll,"eEeSwitch ! dll ver. = 0%x.0%x.0%x",byte2,byte1,byte0);

}
else
{
sprintf(sz_version_dll,"eEeSwitch ! ");
MessageBox (NULL,"Failed to read FTDI dll version number !","eEeSwitch", MB_ICONERROR);
}

SetWindowText(hwnd,sz_version_dll);


*/






break;

case WM_SIZE:
if(options_flag == 0)
{
bresult = SetWindowPos (hwnd,
HWND_TOP,
20,
20,
42 * cxChar,
40 * cyChar,
SWP_NOMOVE);
}
if(options_flag == 1)
{
bresult = SetWindowPos (hwnd,
HWND_TOP,
20,
20,
100 * cxChar,
40 * cyChar,
SWP_NOMOVE);
}
break;

case WM_PAINT:
Draw_status_box(cxChar, cyChar);

Update_leds(cxChar,cyChar,led_state);

break;


case WM_COMMAND:

switch (wParam)
{
case Checkbox:
options_flag = (int) SendMessage (hwndButton[0], BM_GETCHECK, 0, 0) ;
if(options_flag == 0)
{
bresult = SetWindowPos (hwnd,
HWND_TOP,
20,
20,
42 * cxChar,
40 * cyChar,
SWP_NOMOVE);
}
if(options_flag == 1)
{
bresult = SetWindowPos (hwnd,
HWND_TOP,
20,
20,
100 * cxChar,
40 * cyChar,
SWP_NOMOVE);
}
break;

case Button1:
masked_led_state = led_state & 1;
if (masked_led_state == 0)
{
led_state = led_state | 1;
Button = 1;
status = WriteButtonLabel(&configdata,hwndButton[1],Button,led_state);
}
else
{
led_state = led_state & 254;
Button = 1;
status = WriteButtonLabel(&configdata,hwndButton[1],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button2:
masked_led_state = led_state & 2;
if (masked_led_state == 0)
{
led_state = led_state | 2;
Button = 2;
status = WriteButtonLabel(&configdata,hwndButton[2],Button,led_state);
}
else
{
led_state = led_state & 253;
Button = 2;
status = WriteButtonLabel(&configdata,hwndButton[2],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button3:
masked_led_state = led_state & 4;
if (masked_led_state == 0)
{
led_state = led_state | 4;
Button = 3;
status = WriteButtonLabel(&configdata,hwndButton[3],Button,led_state);
}
else
{
led_state = led_state & 251;
Button = 3;
status = WriteButtonLabel(&configdata,hwndButton[3],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button4:
masked_led_state = led_state & 8;
if (masked_led_state == 0)
{
led_state = led_state | 8;
Button = 4;
status = WriteButtonLabel(&configdata,hwndButton[4],Button,led_state);
}
else
{
led_state = led_state & 247;
Button = 4;
status = WriteButtonLabel(&configdata,hwndButton[4],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button5:
masked_led_state = led_state & 16;
if (masked_led_state == 0)
{
led_state = led_state | 16;
Button = 5;
status = WriteButtonLabel(&configdata,hwndButton[5],Button,led_state);
}
else
{
led_state = led_state & 239;
Button = 5;
status = WriteButtonLabel(&configdata,hwndButton[5],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button6:
masked_led_state = led_state & 32;
if (masked_led_state == 0)
{
led_state = led_state | 32;
Button = 6;
status = WriteButtonLabel(&configdata,hwndButton[6],Button,led_state);
}
else
{
led_state = led_state & 223;
Button = 6;
status = WriteButtonLabel(&configdata,hwndButton[6],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button7:
masked_led_state = led_state & 64;
if (masked_led_state == 0)
{
led_state = led_state | 64;
Button = 7;
status = WriteButtonLabel(&configdata,hwndButton[7],Button,led_state);
}
else
{
led_state = led_state & 191;
Button = 7;
status = WriteButtonLabel(&configdata,hwndButton[7],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

case Button8:
masked_led_state = led_state & 128;
if (masked_led_state == 0)
{
led_state = led_state | 128;
Button = 8;
status = WriteButtonLabel(&configdata,hwndButton[8],Button,led_state);
}
else
{
led_state = led_state & 127;
Button = 8;
status = WriteButtonLabel(&configdata,hwndButton[8],Button,led_state);
}
Update_leds(cxChar,cyChar,led_state);
break;

}
break; // end wm_command.
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}




//**********************************************************************************************************************
//**********************************************************************************************************************
// MAIN PROGRAMLOOP

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
MSG msg;
WNDCLASSEX wndclass ;
//HINSTANCE dllhandle = 0;
HWND hConfigFile;

int return_status=0;
int cxChar , cyChar;

DWORD dwFileSize;

char szconfigfilenname[] = "eeeswitch.cfg";
char szAppName[] = "eeeSwitch";


// Get a handle to the DLL module.
dllhandle = LoadLibrary("FTD2XX.dll");
// If the handle is valid, try to get the function address.
if (dllhandle == NULL)
{
MessageBox (NULL,"FTD2XX.dll not found, make sure D2XX drivers are installed !",szAppName, MB_ICONERROR);
FTDI_enable_flag = 0;
}

if (dllhandle != NULL)
{
CVI_FT_ListDevices = (pntr_FT_ListDevices) GetProcAddress(dllhandle,"FT_ListDevices");
CVI_FT_OpenEx = (pntr_FT_OpenEx) GetProcAddress(dllhandle,"FT_OpenEx");
CVI_FT_Close = (pntr_FT_Close) GetProcAddress(dllhandle,"FT_Close");
CVI_FT_GetDriverVersion = (pntr_FT_GetDriverVersion) GetProcAddress(dllhandle,"FT_GetDriverVersion");
CVI_FT_GetLibraryVersion = (pntr_FT_GetLibraryVersion) GetProcAddress(dllhandle,"FT_GetLibraryVersion");
CVI_FT_SetBitMode = (pntr_FT_SetBitMode) GetProcAddress(dllhandle,"FT_SetBitMode");
CVI_FT_GetBitMode = (pntr_FT_GetBitMode) GetProcAddress(dllhandle,"FT_GetBitMode");
CVI_FT_Read = (pntr_FT_Read) GetProcAddress(dllhandle,"FT_Read");
CVI_FT_Write = (pntr_FT_Write) GetProcAddress(dllhandle,"FT_Write");
CVI_FT_SetBaudRate = (pntr_FT_SetBaudRate) GetProcAddress(dllhandle,"FT_SetBaudRate");
CVI_FT_SetDivisor = (pntr_FT_SetDivisor) GetProcAddress(dllhandle,"FT_SetDivisor");
CVI_FT_SetLatencyTimer = (pntr_FT_SetLatencyTimer) GetProcAddress(dllhandle,"FT_SetLatencyTimer");
CVI_FT_GetLatencyTimer = (pntr_FT_GetLatencyTimer) GetProcAddress(dllhandle,"FT_GetLatencyTimer");
CVI_FT_SetUSBParameters = (pntr_FT_SetUSBParameters) GetProcAddress(dllhandle,"FT_SetUSBParameters");
CVI_FT_GetQueueStatus = (pntr_FT_GetQueueStatus) GetProcAddress(dllhandle,"FT_GetQueueStatus");
CVI_FT_GetStatus = (pntr_FT_GetStatus) GetProcAddress(dllhandle,"FT_GetStatus");
CVI_FT_Purge = (pntr_FT_Purge) GetProcAddress(dllhandle,"FT_Purge");
}

// Configfile reading or writing.
hConfigFile = CreateFile (szconfigfilenname, // pointer to name of the file
GENERIC_WRITE | GENERIC_READ, // access (read-write) mode
0, //Don't share the file. // share mode
NULL, // pointer to security attributes
OPEN_ALWAYS, //Open the file, if not exist create it.
0, // // file attributes
NULL);

if(hConfigFile == NULL)
{
MessageBox(NULL, "Config file error ! Please check read/write permissions !", "Error!",MB_ICONEXCLAMATION | MB_OK);
return 0;
}

if(hConfigFile != INVALID_HANDLE_VALUE)
{


dwFileSize = GetFileSize(hConfigFile, NULL);

if (dwFileSize < 2)// create configfile and write default values if it does not exist.
{
return_status = Create_Config_File(hConfigFile);
}
if(dwFileSize != 0xFFFFFFFF)// If it exists read it into a buffer.
{
return_status = Read_Config_File(hConfigFile,dwFileSize);
if(return_status == 16)
{
MessageBox(NULL, "Config file error ! Please check configfile !", "Error!",MB_ICONEXCLAMATION | MB_OK);
}
}
CloseHandle(hConfigFile);
}

// Main window class declaratie.
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = szAppName ;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

if (!RegisterClassEx (&wndclass))
{
MessageBox (NULL,"This program requires Windows NT!",szAppName, MB_ICONERROR) ;
return 0 ;
}

cxChar = LOWORD (GetDialogBaseUnits ()) ;
cyChar = HIWORD (GetDialogBaseUnits ()) ;

hwnd = CreateWindowEx (WS_EX_APPWINDOW,
szAppName, // window class name
"eeeSwitch", // window caption
WS_OVERLAPPEDWINDOW,// | WS_VSCROLL | WS_HSCROLL, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
42 * cxChar, // initial x size
40 * cyChar, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL // creation parameters
);


if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);
return 0;
}
DeleteObject ((HGDIOBJ) SetClassLong (hwnd, GCL_HBRBACKGROUND,(LONG) CreateSolidBrush (RGB (212,208 ,200))));
InvalidateRect (hwnd, NULL, TRUE);

ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd);

//**********************************************************************************************************************
// messageloop .
while (GetMessage (&msg, NULL, 0, 0) > 0) // > 0 betekent windows boodschappen.
{ // -1 betekent error. 0 is het resultaat in de MQ van PostQuitMessage.
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
 
May 11, 2008
23,331
1,575
126
I forgot to add that when i use the same dll in CVI , it works flawlessly in debug and release mode.


I have this only in borland.


I am still searching and i am afraid that it maybe has something to do with the calling convention:


The ftdiheader uses :

__declspec


and what i learned from googling is that the dll's in windows use the __stdcall.

Can that be the case ?
 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
The only thing that comes to mind (for me)...

Is that in debug mode, your variables are usually padded with extra space or filler. So if you have any memory corruption, you might not see it in debug mode, and you will see it in release mode.

I don't see anything particularly wrong with your code (using the GetProcAddress, etc) but its been awhile since I've had to do that.

The only thing I can suggest is make a new project (copy the code) and do something similar but remove any extra fluff like the reading of the config file. If that works then obviously there is something wrong with the config file code and its a nice place to start looking. But I'll look over your code again real quick looking for anything out of the ordinary and I'll respond again if I see something.
 
May 11, 2008
23,331
1,575
126
Hello,

I have found a way to work around it.


I use all the ftdi functions inside the "winmain" and inside the callback "wndproc".
This way i have been able to tackle that problem. It works now and gives me time to figure out what was happening.


My program works and i am able to modify the settings in my config file from within the gui.
It makes it a lot more user friendly. I want to be able to TAB through the setting boxes but i get into trouble there. I am trying to create a second callback but for some reason i get into calling convention errors. I am new to subclassing and still finding out why.



I bought the book "programming windows" 5th edition from charles petzold. That's how i started learning win32 programming.
Some of the example programs just won't compile. And i figured out most problems that have mainly to do with converting one type into another. I need a lot of casting.
I am getting there but sometimes it's just annoying. I come from a plane assembly background for microcontrollers and in the past Z80.
It is fun to see that my own functions always work at once but that i run into trouble a lot with the window specific functions. I am new to C and C++, but it'not that difficult as i expected. It's more that you have to know the quirks. Compiler specifics and those kind of things. I am using borland C++ builder but those examples are made for visual studio.
And there are differences. I will get there. When it comes to technical stuff i always do.

If you want to see the whole program i can show it to you, it is still beta but when it is finished i am planning to opensource it anyway. Sooner or later i am planning to make a website where i will put all my schematics, programs and idea's on my website.




 
May 11, 2008
23,331
1,575
126
I had similair exceptions as my first post when i use complex for loops in my program.

Well, i found why i had these exceptions.

In some complex for loops i have used in my program, the compiler has serious issues to make good assembly code when i have the "Optimize for speed" setting selected. When i select "no optimisations" or "None", the exceptions are gone. Maybe this also works for the problem i mentioned above...

All of this is the case in release mode. When in debug mode i do not have these exceptions.



I also found a setting in the compiler where i can choose different calling conventions.
This too may resolve the issues i had with the FTDI dll.
All of this is under the compiler tab.


At this moment i am very happy :laugh:
 
May 11, 2008
23,331
1,575
126
Just tested something extra.

When i choose optimise for speed and select the standard call calling convention these exception errors (with the complex for loops) are solved.

Tomorrow i will test if i can now call the ftdi dll from outside the winmain and callback winproc. This would greatly cleanup my code if this is the solution.
 
May 11, 2008
23,331
1,575
126
Hooray, that worked too :D. I am pleased. I will set up an account on photobucket. This way i can show screenshots. It just might come in handy.