|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Functional IDE DLL call compiles to non-functional DLL callHello All,
I wrote a DLL in VC++, and in my VB program I've declared each of the functions with absolute paths to the compile directory of the .DLL. When I click "Start with Full Compile," the program runs in the IDE and executes each .DLL call perfectly. However, when I compile the program to an .EXE, the program doesn't call the .DLL's functions any longer. Furthermore, the .EXE exits with the attached error message. I'm running on Win2k. Any ideas? Thanks! Joel Whitehouse wrote:
> Hello All, If this is a standard DLL, show us the C++ prototypes and the VB Declares, and a representative call to each. What you posted isn't enough to diagnose this.> > I wrote a DLL in VC++, and in my VB program I've declared each of the > functions with absolute paths to the compile directory of the .DLL. > When I click "Start with Full Compile," the program runs in the IDE > and executes each .DLL call perfectly. > > However, when I compile the program to an .EXE, the program doesn't > call the .DLL's functions any longer. Furthermore, the .EXE exits > with the attached error message. > > I'm running on Win2k. Any ideas? Jim Mack wrote:
Show quoteHide quote > Joel Whitehouse wrote: Coming right up.> >>Hello All, >> >>I wrote a DLL in VC++, and in my VB program I've declared each of the >>functions with absolute paths to the compile directory of the .DLL. >>When I click "Start with Full Compile," the program runs in the IDE >>and executes each .DLL call perfectly. >> >>However, when I compile the program to an .EXE, the program doesn't >>call the .DLL's functions any longer. Furthermore, the .EXE exits >>with the attached error message. >> >>I'm running on Win2k. Any ideas? > > > If this is a standard DLL, show us the C++ prototypes and the VB Declares, and a representative call to each. What you posted isn't enough to diagnose this. > Mr. Mack,
Thanks for your help - here is the code you requested. Like I say, it works in the VB IDE, but not when compiled... Here are the VB Declares: ---------------------------------------------------------------------------- Public Declare Function Calibrate Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" (ByVal hWnd As Long, ByVal Msg As Long) As Integer Public Declare Function Initialize Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" (ByVal lpszFileName As String, ByVal hWnd As Long) As Integer Public Declare Function MoveAz Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" (ByVal hWnd As Long, ByVal Msg As Long, ByVal nAzimuth As Long) As Integer Public Declare Function MoveEl Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" (ByVal hWnd As Long, ByVal Msg As Long, ByVal nElevation As Long) As Integer Public Declare Function StopMast Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" Alias "Stop" () As Integer Public Declare Function IsMastAlive Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" Alias "IsAlive" (ByRef answer As Boolean) As Integer Public Declare Function IsMastMoving Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" Alias "IsMoving" (ByRef directons As Long) As Integer Public Declare Function NotifyOnComplete Lib "C:\MyProjects\MastControllerLibrary\MastController\Debug\MastController.dll" (ByVal hWnd As Long, ByVal Msg As Long) As Integer And the c++ Prototypes ------------------------------------------------------------------------------ AFX_API_EXPORT HRESULT PASCAL Calibrate( HWND hWnd, UINT Msg ); AFX_API_EXPORT HRESULT PASCAL Initialize( LPCTSTR lpszFileName, HWND hWnd ); AFX_API_EXPORT HRESULT PASCAL MoveAz( HWND hWnd, UINT Msg, INT nAzimuth ); AFX_API_EXPORT HRESULT PASCAL MoveEl( HWND hWnd, UINT Msg, INT nElevation ); AFX_API_EXPORT HRESULT PASCAL Stop( void ); AFX_API_EXPORT HRESULT PASCAL IsAlive( BOOL & isAlive ); AFX_API_EXPORT HRESULT PASCAL IsMoving(INT & directions); AFX_API_EXPORT HRESULT PASCAL NotifyOnComplete(HWND hWnd, UINT Msg); And a representative call to each: ------------------------------------------------------------------------------- Public Function IsAlive() As Boolean On Error Resume Next IsMastAlive IsAlive End Function Public Function IsMoving() As Long On Error Resume Next IsMastMoving IsMoving End Function Public Sub Az(ByVal azimuth As Integer) On Error Resume Next GoNotifyOnComplete MoveAz Form1.hWnd, UWM_MOVE_AZ_THREAD, CLng(azimuth) End Sub Public Sub El(ByVal elevation As Integer) On Error Resume Next GoNotifyOnComplete MoveEl Form1.hWnd, UWM_MOVE_EL_THREAD, CLng(elevation) End Sub Private Sub GoNotifyOnComplete() On Error Resume Next 'Do this just once Static x As Boolean If (x = False) Then NotifyOnComplete Form1.hWnd, UWM_MOVEMENT_COMPLETE x = True End If End Sub Public Sub InitializeMast(iniFilePath As String) On Error Resume Next Initialize iniFilePath, Form1.hWnd End Sub Public Sub HaltMast() On Error Resume Next StopMast End Sub Public Sub CalibrateMast() On Error Resume Next Calibrate Form1.hWnd, UWM_CALIBRATE_THREAD End Sub Joel Whitehouse wrote:
Show quoteHide quote > Mr. Mack, If you hadn't said that these work perfectly in the IDE, I'd say that they could never have worked at all, since you're using the Pascal calling convention, whereas VB uses and expects _stdcall.> > Thanks for your help - here is the code you requested. Like I say, it > works in the VB IDE, but not when compiled... > > Here are the VB Declares: > ---------------------------------------------------------------------------- > Public Declare Function Calibrate Lib > (ByVal hWnd As Long, ByVal Msg As Long) As Integer > Public Declare Function Initialize Lib > (ByVal lpszFileName As String, ByVal hWnd As Long) As Integer > Public Declare Function MoveAz Lib > (ByVal hWnd As Long, ByVal Msg As Long, ByVal nAzimuth As Long) As > Integer Public Declare Function MoveEl Lib > (ByVal hWnd As Long, ByVal Msg As Long, ByVal nElevation As Long) As > Integer Public Declare Function StopMast Lib > Alias "Stop" () As Integer > Public Declare Function IsMastAlive Lib > Alias "IsAlive" (ByRef answer As Boolean) As Integer > Public Declare Function IsMastMoving Lib > Alias "IsMoving" (ByRef directons As Long) As Integer > Public Declare Function NotifyOnComplete Lib > (ByVal hWnd As Long, ByVal Msg As Long) As Integer > > > And the c++ Prototypes > ------------------------------------------------------------------------------ > AFX_API_EXPORT HRESULT PASCAL Calibrate( HWND hWnd, UINT Msg ); > AFX_API_EXPORT HRESULT PASCAL Initialize( LPCTSTR lpszFileName, HWND > hWnd ); > AFX_API_EXPORT HRESULT PASCAL MoveAz( HWND hWnd, UINT Msg, INT > nAzimuth ); AFX_API_EXPORT HRESULT PASCAL MoveEl( HWND hWnd, UINT > Msg, INT nElevation ); AFX_API_EXPORT HRESULT PASCAL Stop( void ); > AFX_API_EXPORT HRESULT PASCAL IsAlive( BOOL & isAlive ); > AFX_API_EXPORT HRESULT PASCAL IsMoving(INT & directions); > AFX_API_EXPORT HRESULT PASCAL NotifyOnComplete(HWND hWnd, UINT Msg); > > > > And a representative call to each: > ------------------------------------------------------------------------------- > > Public Function IsAlive() As Boolean > On Error Resume Next > IsMastAlive IsAlive > End Function > > Public Function IsMoving() As Long > On Error Resume Next > IsMastMoving IsMoving > End Function > > Public Sub Az(ByVal azimuth As Integer) > On Error Resume Next > GoNotifyOnComplete > MoveAz Form1.hWnd, UWM_MOVE_AZ_THREAD, CLng(azimuth) > End Sub > > Public Sub El(ByVal elevation As Integer) > On Error Resume Next > GoNotifyOnComplete > MoveEl Form1.hWnd, UWM_MOVE_EL_THREAD, CLng(elevation) > End Sub > > Private Sub GoNotifyOnComplete() > On Error Resume Next > 'Do this just once > Static x As Boolean > If (x = False) Then > NotifyOnComplete Form1.hWnd, UWM_MOVEMENT_COMPLETE > x = True > End If > End Sub > > Public Sub InitializeMast(iniFilePath As String) > On Error Resume Next > Initialize iniFilePath, Form1.hWnd > End Sub > > Public Sub HaltMast() > On Error Resume Next > StopMast > End Sub > > Public Sub CalibrateMast() > On Error Resume Next > Calibrate Form1.hWnd, UWM_CALIBRATE_THREAD > End Sub It isn't difficult to accommodate pascal convention, just reverse the order of arguments. For example, AFX_API_EXPORT HRESULT PASCAL MoveEl( HWND hWnd, UINT Msg, INT nElevation ); ...becomes: Declare Function MoveEl Lib "xxx" _ (ByVal nElevation As Long, _ ByVal Msg As Long, _ ByVal hWnd As Long) As Integer But it might be better overall to switch to _stdcall in the DLL. Further, 'int' or 'uint' in C is always Long in VB, and that applies to HRESULT as well. None of your parameters or return types should be "As Integer" in VB. And a 'bool' in C is different than a Boolean in VB. C 'bool' is equivalent to VB Long, with the values 0 and 1, not the 0 and -1 that you'd expect from VB. Last, I can't say that I've ever seen C parameters listed as "INT & directions". I suspect that you mean "INT *directions", which would square with your use of ByRef in the VB Declare. > If you hadn't said that these work perfectly in the IDE, I'd say that they could never have worked at all, since you're using the Pascal calling convention, whereas VB uses and expects _stdcall. Wow - that is completely not intuitive... Why *is* that?> > It isn't difficult to accommodate pascal convention, just reverse the order of arguments. For example, > > AFX_API_EXPORT HRESULT PASCAL MoveEl( HWND hWnd, UINT Msg, INT nElevation ); > > ...becomes: > > Declare Function MoveEl Lib "xxx" _ > (ByVal nElevation As Long, _ > ByVal Msg As Long, _ > ByVal hWnd As Long) As Integer > Thanks so much for this info - I seached for it online but didn't have a > But it might be better overall to switch to _stdcall in the DLL. > > Further, 'int' or 'uint' in C is always Long in VB, and that applies to HRESULT as well. None of your parameters or return types should be "As Integer" in VB. And a 'bool' in C is different than a Boolean in VB. C 'bool' is equivalent to VB Long, with the values 0 and 1, not the 0 and -1 that you'd expect from VB. great deal of success. > Last, I can't say that I've ever seen C parameters listed as "INT & directions". I suspect that you mean "INT *directions", which would square with your use of ByRef in the VB Declare. So a VB Byref casts to a C pointer?> Thank you sir for all your time - I think I have a lot to go on here! -Joel Joel Whitehouse wrote:
Show quoteHide quote >> If you hadn't said that these work perfectly in the IDE, I'd say Intuition should play very little role in programming. :-)>> that they could never have worked at all, since you're using the >> Pascal calling convention, whereas VB uses and expects _stdcall. >> >> It isn't difficult to accommodate pascal convention, just reverse >> the order of arguments. For example, >> >> AFX_API_EXPORT HRESULT PASCAL MoveEl( HWND hWnd, UINT Msg, INT >> nElevation ); >> >> ...becomes: >> >> Declare Function MoveEl Lib "xxx" _ >> (ByVal nElevation As Long, _ >> ByVal Msg As Long, _ >> ByVal hWnd As Long) As Integer > > Wow - that is completely not intuitive... Why *is* that? It is that because that's what it is. Pascal convention has always been to pass from left to right, as was the older Basic convention. C convention, and now stdcall, has always been to pass from right to left. There may be reasons from the deep history of the languages, but in practical terms it just is that way, so we deal with it. Actually, since I never use Pascal convention, I don't know for certain that C++ doesn't perform some trickery to do the order reversal for you. I doubt it, but anything is possible. Mr. Mack,
I fixed all of the calls and declarations, and I still get the error. If I put the c++ .dll in the C:\ root, and change all the declares paths to C:\, then the program still works in the IDE. However, I compiled the VB code and removed the "On Error Resume Next" lines form the VB functions that call the my dll, to try to get at teh answer. Whenever I try to call one of teh Declared .dll functions, I get "Run Time error 53: File not found: C:\mydll.dll", despite the dact that mydll.dll is *obviously* in the root directory. I have no idea why the compiled VB code does this when the IDE code does not. I guess I'm wondering if you have any firther ideas, and if you had any tips for converting a pascal call to __stdcall. Thanks! -Joel Joel Whitehouse wrote:
Show quoteHide quote > Mr. Mack, "File not found" can mean the named file, or a dependency of that file. Use Depends.exe to load and run your compiled program, and I'll bet a missing dependent DLL shows up.> > I fixed all of the calls and declarations, and I still get the error. > > If I put the c++ .dll in the C:\ root, and change all the declares > paths to C:\, then the program still works in the IDE. > > However, I compiled the VB code and removed the "On Error Resume Next" > lines form the VB functions that call the my dll, to try to get at teh > answer. Whenever I try to call one of teh Declared .dll functions, I > get "Run Time error 53: File not found: C:\mydll.dll", despite the > dact that mydll.dll is *obviously* in the root directory. I have no > idea why the compiled VB code does this when the IDE code does not. > > I guess I'm wondering if you have any firther ideas, and if you had > any tips for converting a pascal call to __stdcall. > It's always best to put your DLL in Win/Sys, and leave off any path information from the Declare. Placing it in the application directory is the next best, again with no explicit path in the Lib clause. Even if it doesn't contribute to this problem, I'd strongly encourage you to switch to stdcall, since the Windows API is built around that and VB is most comfortable with it. Changing to stdcall could be as simple as either replacing the keyword pascal with __stdcall, or just dropping the pascal with no other change. I don't know how the other bits on your prototypes are #defined, but something with 'API' in the name may have __stdcall as part of it already. > Changing to stdcall could be as simple as either replacing the keyword pascal with __stdcall, or just dropping the pascal with no other change. I don't know how the other bits on your prototypes are #defined, but something with 'API' in the name may have __stdcall as part of it already. I found this in an attached header:#define PASCAL __stdcall My dependancies appear to be intact... Heh heh. I'm gonna be sick. I've got a god year and an half into this project... It's *almost* done, and then this. Ugh. -Joel Joel Whitehouse wrote:
>> Changing to stdcall could be as simple as either replacing the Oooh, that's just evil. But it does explain why it worked in the IDE, when it shouldn't have if it were using pascal calling convention.>> keyword pascal with __stdcall, or just dropping the pascal with no >> other change. I don't know how the other bits on your prototypes >> are #defined, but something with 'API' in the name may have >> __stdcall as part of it already. > > I found this in an attached header: > > #define PASCAL __stdcall > My dependancies appear to be intact... Without digging into the DLL source it's not possible to go much further. I would suggest that you compile the DLL with no optimizations and with all possible checks turned on, to see if there is some assumption being made that is biting you.I would also take a look at the exported entry points, in stdcall format. There should be, for example, an entry named _Calibrate@8. If it says anything else, for instance _Calibrate@12, then you know where the problem lies -- hidden parameters. At a minimum, you could just open the DLL in a hex editor and look for the string _Calibrate. "Floating point inexact result" is a pretty specific-seeming error, and I can see no way that it could be generated by the act of making the calls, so it well could be a side effect of stack misalignment. The IDE will hide stack misalignments that a compiled app will reveal. You might also compile the VB to pcode instead of native, which (I think) will also hide them. > Heh heh. I'm gonna be sick. I've got a god year and an half into If none of the above yields any joy, I can put you in touch with a true C++/VB expert who can (for a fee) look over your work and possibly see something that you can't, being too close to it. Let me know by email if that interests you.> this > project... It's *almost* done, and then this. Ugh. -- Jim "Joel Whitehouse" <joelwhiteho***@gmail.com> wrote in message pascal with __stdcall, or just dropping the pascal with no other change. Inews:%231Vuc8agFHA.2472@TK2MSFTNGP15.phx.gbl... > > > Changing to stdcall could be as simple as either replacing the keyword don't know how the other bits on your prototypes are #defined, but something with 'API' in the name may have __stdcall as part of it already. > You are trying to import a MFC DLL into VB using the Function Declare> I found this in an attached header: > > #define PASCAL __stdcall > > My dependancies appear to be intact... > > Heh heh. I'm gonna be sick. I've got a god year and an half into this > project... It's *almost* done, and then this. Ugh. > > -Joel directive, and using C++ compiler directives to create your 'export' signatures (__declspec(dllexport)). This can cause problems for three reasons: 1) Your signatures, depending on compiler options (even seemingly harmless ones), may not come out quite the way you expect, or more importantly the way VB expects, and 2) You are defining arguments (parameters) that VB hasn't a clue about (but is ready and willing to give a good guess about <g>), and 3) The Function Declare directive works slightly differently in the IDE than it does with compiled code. (As you have discovered.) Any of these items can conspire to produce strange results. The easiest fix is to use a .def file to create your export files. Gives somewhat better control - what you type is what you get. You can also use a typelib, a superior solution to using Function Declares - the chief advantage of which is - calls to a typedef will fail the same in the IDE as it would if compiled. <g> Second, I would remove the 'References' in your parameters (the BOOL&, ...). I know references are implemented in C++ as pointers, and that most of the time there is little difference in marshelling between a pointer and a reference. But call me superstitious. Third, the same with the 'BOOL' - a C++ BOOL and a VB Boolean may work alike most of the time, but, again, they ain't the same and you can get burned. Shorts are usually safe and don't forget to check for -1. Fourth, a C++ 'int' is a VB 'long' and a VB 'integer' is a C++ 'short'. Hard to get more specific without having the project in front of me. hth -ralph Slight correction...
s/calls to a typedef will fail the same in the IDE as it would if compiled./ calls using a typelib will fail the same in the IDE as it would if compiled/g On Tue, 5 Jul 2005 14:12:37 -0400, "Jim Mack" <jmack@mdxi.nospam.com> in <eMA7g0YgFHA.3***@TK2MSFTNGP14.phx.gbl> wrote: >> Wow - that is completely not intuitive... Why *is* that? That's absolutely unequivocally true except when debugging.> >Intuition should play very little role in programming. :-) --- Stefan Berglund
Problem comparing double values
Programatically design a form Divide a path into a Drivename, Pathname, and Filename? Testing for MAPI , again How should I select a folder, create and select the folder? SaveSetting question Default Property in VB6 Class Return Security Events for Yesterday Help with WMI Emergency: Unicode Characters in a Dataset. |
|||||||||||||||||||||||