LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Getting error 1097 when try to call DLL from Labview

Solved!
Go to solution

I had to write a wrapper DLL to use some functions in a third party's DLL, and I'm having some issues. I created an executable to test my code and it works fine, but when I try to run the same function through the DLL I created in Labview, I get error 1097. I've read through most of the posts on this forum about that issue, but none of the solutions offered are working for me. I'm pretty sure it's not an issue of passing the parameters to the CLFN because I've changed the function so it only accepts one simple input (a number that it gets from a subvi that came from the third party's DLL; this input works with a bunch of other functions so I don't think that's the issue).

 

I've attached the C code that creates the wrapper, though I'm not sure how helpful it is without being familiar with the original DLL's functions. I'm hoping someone can spot something basic I'm missing from my code, but please let me know if I should attach anything else.

 

I'm using a Labview 32 bit version 2012 on a 64 bit Windows 7 computer.

 

Thanks in advance for any help!

0 Kudos
Message 1 of 9
(5,030 Views)

Actually I don't see anything that would be particular problematic to be called by the Call Library Node directly.

 

However that said, the code is somewhat involved and error handling is weird. Instead of just calling all the functions in serie and at the end adding all error codes up, you should do proper error handling after each call and bail out as soon as you encounter an error. The way you do it there is a remote change that your function returns with a 0 error indication while several of the functions have returned an error.

 

And you do not show any declarations of the actual driver but declare all the functions pointers on your own. Are you sure you declared them exactly as the original. The way you did it, the C compiler will have no way to verify that your declaration matches the original ones. So missing a parameter in your declaration is enough to cause a crash. Also your declaration says nothing about the calling convention. Visual C by default uses cdecl, unless you change that in the project settings or pass it an according command line parameter. Are you sure the original DLL uses cdecl for its functions?

Rolf Kalbermatter
My Blog
0 Kudos
Message 2 of 9
(5,011 Views)

Hi roflk,

 

Thanks so much for your help. Your error handling tips were just what I needed; I realized that the host library wasn't being opened correctly (hInstLibrary was returning false). I was able to fix this by adding another CLFN that called a random function from the host library in my VI, and this allowed me to run my wrapper code. Just curious, is that standard operating procedure for using a wrapper DLL or am I using some loophole that I shouldn't be doing?

 

Thanks again,

Renee

0 Kudos
Message 3 of 9
(4,981 Views)

@happyhippoday wrote:

Hi roflk,

 

Thanks so much for your help. Your error handling tips were just what I needed; I realized that the host library wasn't being opened correctly (hInstLibrary was returning false). I was able to fix this by adding another CLFN that called a random function from the host library in my VI, and this allowed me to run my wrapper code. Just curious, is that standard operating procedure for using a wrapper DLL or am I using some loophole that I shouldn't be doing?

 

Thanks again,

Renee


Well since you do only load the library with it's unqualified name, you have to make sure Windows can find it. Basically if you use a full path LoadLibrary will only check for that library, either already loaded into memory from that path, or on disk on exactly that location as the path identifies. If neither of these two cases is satisfied, the LoadLibrary() call will fail.

 

With unqualified name (just the DLL file only) Windows will look in a number of locations. These are in this order:

 

1) A module with that name already loaded into the current process

2) The DLL located in the same directory as the current processes executable

3) The System directory

4) The Windows directory

5) Any directory named in the PATH environment variable

 

If Windows can't find the DLL in any of these locations, or other DLLs this DLL depends on directly, then the LoadLibrary() call will fail.

 

Option 5) is a pain in the ass to use, option 4) is highly unusual and should not be used anymore

Option 3) is only recommended for software where the developer knows what he is doing and also creates a seperate installer for all the software components

Option 2) is the prefered way for DLLs that you want to use in your own application without risking to break other application that might use the same DLL name

Option 1) is basically what you have created for now but which is really not a good solution like that. Just referencing the DLL somewhere else by full path, which your Call Library Node currently does to have it loaded is quite a hack really.

Rolf Kalbermatter
My Blog
0 Kudos
Message 4 of 9
(4,970 Views)

Hi roflk,

 

Sorry for the late reply. Thanks so much for the information; it's greatly appreciated. If I want to implement the recommended option 2 that you talked about above (having the DLL located in the same directory as the current process's executable), does that mean I should save the VI (the process's executable?) in the same folder as where the DLL is located? I tried that and it's still looking like the library isn't being called.

 

Thanks again,

Renee

0 Kudos
Message 5 of 9
(4,902 Views)

The location of the VI itself is not really that important for this. Are you sure that you only enter the DLL name without any path information in the Library Name box in the CLN configuration? Also are you sure the DLL does not depend on other DLLs that might need to get installed somewhere too?

 

What does "it's still looking like the library isn't being called" mean? If you enter the DLL name in the CLN and the VI is not broken, the DLL is definitely loaded into memory. If it "seems" the DLL is not called then that can only be because your LabVIEW code does not cause the CLN to be called, not because the DLL is not found.

Rolf Kalbermatter
My Blog
0 Kudos
Message 6 of 9
(4,899 Views)

Sorry for the confusion. When I say it looks like the library isn't being called, I mean that the wrapper DLL I built isn't able to load the original third-party library correctly (hInstLibrary = LoadLibrary(the third-party DLL) is returning false.

 

I added error handling in my program so that it returns a certain code when this happens and exits the program. If I don't have that error handling added, I get the 1097 error I posted about initially. So yes, this DLL I'm trying to run does depend on the third-party DLL that needs to get installed first. The issue is I haven't been able to get my wrapper DLL to open the third-party DLL without first calling the third-party DLL in a CLN (which isn't too big of a deal since my code is working if I do this, but I would prefer to do this without cheating, which it seems like my setup is doing right now).

 

If I try to enter only the DLL name without any path information in the Library Name box in the CLN configuration, it still asks me for a path and populates it anyway. (As a side note, when this happens, it says loading DLL, so I'm assuming this means that it's loaded fine?)

 

So my set-up right now is:
A CLN with the path to my wrapper DLL that loads the third-party DLL

Both the wrapper DLL and the third-party DLL in the same folder that the path in the CLN is pointing to


Am I missing a step?

 

Thanks,

Renee

0 Kudos
Message 7 of 9
(4,870 Views)
Solution
Accepted by topic author happyhippoday

You should read the whole documentation about LoadLibrary() and understand it. Basically if you provide a full path to LoadLibrary() the DLL MUST be present at that location in order for LoadLibrary() to succeed. If you only pass in the DLL name Windows will ONLY search in these locations:

 

1) if the module (DLL) is already loaded it will return a handle to the loaded module and increment its reference count

 

2) if the referencing module contains a manifest (either embedded in the module image or in a seperate manifest file in the same directory as the executablemodule) specyfying a version number for this DLL it will load that DLL with that version from the SxS (Side by Side) location and fail if it is not present

 

3) if the loading executable contains a manifest (either embedded in the executable or in a seperate manifest file in the same directory as the executable) specyfying a version number for this DLL it will load that DLL with that version from the SxS (Side by Side) location and fail if it is not present

 

4) it will search for the DLL in the same directory as the directory from which the current process image is loaded. This is NOT the directory of the DLL trying to load the other DLL BUT the directory where the EXE file is located from which the process was created.

 

5) The system directory

 

6) The Windows directory

 

7) Any directory in the PATH environment variable

 

😎 the current path directory which is a location maintained by windows per process and changed both explicitedly when the application calls the SetCurrentDirectory() API but also implicitedly by things like the file selection dialog whenever it is dismissed in other ways than the cancel operation.

 

Basically putting your dependend DLL into the same directory as the wrapper DLL will NOT work when using the DLL name only UNLESS you place both DLLs into the same directory as your executable. If you do not want this restriction and want to be able to move those modules together in different directories, you do have to create in your wrapper the correct path to pass to LoadLibrary(). Basically you need to have code to determine the path location of your wrapper DLL and then strip its own name and append the wrapped DLL name to it and then pass that to LoadLibrary().

 

There are several ways to determine the path of the current module. The easiest if you don't mind to have the DLL name hardcoded in your code would be to call GetModuleFileName(GetModuleHandle("yourDLLname"), buffer, size).

Rolf Kalbermatter
My Blog
0 Kudos
Message 8 of 9
(4,863 Views)

Ahh, I got it, sorry I was misunderstanding which full path I had to specify. The easiest thing for me was just to pass the path of the DLL directly to the LoadLibrary function. It's working now; thank you so much for all your help!

 

Best,

Renee

0 Kudos
Message 9 of 9
(4,851 Views)