LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Call Library Function & DLL Attach and Detach Calls

Hi,

I'd like to run a C/C++ -function (or why not even a LabVIEW VI) on DLL (initialization) attach and DLL exit (detach). The initialization call would be used to check if subVI library license is ok and to display a pop-up for those using a test license and the exit call would be used to close all open files and other things opened using the dll. A DLL can detect four types of maintenance events: DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH. In which situations does LabVIEW call these functions when Call Library Function Node is used?

I made a small test on a few calls to a DLL from LabVIEW and wrote logged each of the above mentioned different initialization and clean-up calls. The order of the calls was following.
DLL_THREAD_ATTACH
DLL_PROCESS_DETACH
DLL_PROCESS_DETACH
DLL_PROCESS_DETACH
DLL_PROCESS_DETACH
DLL_THREAD_DETACH
DLL_PROCESS_DETACH
It seems as if a DLL_PROCESS_ATTACH was never called even though according to MS documentation it should be called when "The DLL is being loaded into the virtual address space of the current process as a result of the process starting up or as a result of a call to LoadLibrary. DLLs can use this opportunity to initialize any instance data or to use the TlsAlloc function to allocate a thread local storage (TLS) index."

So please somebody from NI explain how LabVIEW loads DLLs, calls DLLs and unloads DLLs. What happens when there are calls to the same re-entrant DLL from multiple threads.

Tomi

--
Tomi Maila
0 Kudos
Message 1 of 12
(10,521 Views)
Hi,


First, I'm not from NI...


The DLL_PROCESS_ATTACH *is* called when the dll is loaded into memory. Or at least it used to be called in LV5/6/7. Perhaps there is something wrong with the way you tested it. How did you do this?


BTW. I think it would be better to make a seperate function (like "Validate") that validates the licencing. If you put this in the DLL_PROCESS_ATTACH it will be harder to debug. It will be impossible to see if the licencing was wrong, or something else was wrong. In a custom function you can return a meaningfull code, e.g. "Licence expired", "Licence not valid on this machine", etc. In all other (important) functions you'll have to check the "Validated" flag.


Regards,


Wiebe.


"Tomi M" <x@no.email> wrote in message news:1152643209559-389820@exchange.ni.com...
Hi, I'd like to run a C/C++ -function (or why not even a LabVIEW VI) on DLL (initialization) attach and DLL exit (detach). The initialization call would be used to check if subVI library license is ok and to display a pop-up for those using a test license and the exit call would be used to close all open files and other things opened using the dll. A DLL can detect four types of maintenance events: DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH. In which situations does LabVIEW call these functions when Call Library Function Node is used? I made a small test on a few calls to a DLL from LabVIEW and wrote logged each of the above mentioned different initialization and clean-up calls. The order of the calls was following.DLL_THREAD_ATTACHDLL_PROCESS_DETACHDLL_PROCESS_DETACHDLL_PROCESS_DETACHDLL_PROCESS_DETACHDLL_THREAD_DETACHDLL_PROCESS_DETACHIt seems as if a DLL_PROCESS_ATTACH was never called even though according to MS documentation it should be called when "The DLL is being loaded into the virtual address space of the current process as
a result of the process starting up or as a result of a call to
<a> LoadLibrary</a>. DLLs can use this opportunity to initialize any
instance data or to use the <a href="tlsalloc.htm" target="_blank"> TlsAlloc</a> function
to allocate a thread local storage (TLS) index." So please somebody from NI explain how LabVIEW loads DLLs, calls DLLs and unloads DLLs. What happens when there are calls to the same re-entrant DLL from multiple threads. Tomi
0 Kudos
Message 2 of 12
(10,511 Views)
I used the code below.

#include <iostream>
#include <fstream>

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    using namespace std;
    ofstream out("C:\log.txt", ios::app);
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        out << "DLL_PROCESS_ATTACH" << endl;
        break;
    case DLL_THREAD_ATTACH:
        out << "DLL_THREAD_ATTACH" << endl;
        break;
    case DLL_THREAD_DETACH:
        out << "DLL_THREAD_DETACH" << endl;
        break;
    case DLL_PROCESS_DETACH:
        out << "DLL_PROCESS_DETACH" << endl;
        break;
    }
    return TRUE;
}
Tomi
--
Tomi Maila
0 Kudos
Message 3 of 12
(10,509 Views)

Hi there

though i'm not a fan of CIN you could consider to use them. a CIN provides the routines

CINRun
CINLoad
CINInit
CINAbort
CINSave
CINDispose
CINUnload
CINProperties.

because the CIN-code (*.lsb) is loaded into the VI it's harder to crack the license test.

Best regards
chris

CL(A)Dly bending G-Force with LabVIEW

famous last words: "oh my god, it is full of stars!"
0 Kudos
Message 4 of 12
(10,507 Views)

hi there

i tested your code. DLL_PROCESS_ATTACH is called when i LOAD the VI containing the Call library node (LOAD, not run!).

 

Best regards
chris

CL(A)Dly bending G-Force with LabVIEW

famous last words: "oh my god, it is full of stars!"
0 Kudos
Message 5 of 12
(10,502 Views)
Weird, I don't get DLL_PROCESS_ATTACH called... I tried it with LabVIEW 7.1 and LabVIEW 8.0.1 with the following code.

#include <iostream>
#include <fstream>

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    using namespace std;
    ofstream out("C:\log.txt", ios::app);
    out.setf(ios::unitbuf);
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        out << "DLL_PROCESS_ATTACH";
        break;
    case DLL_THREAD_ATTACH:
        out << "DLL_THREAD_ATTACH";
        break;
    case DLL_THREAD_DETACH:
        out << "DLL_THREAD_DETACH";
        break;
    case DLL_PROCESS_DETACH:
        out << "DLL_PROCESS_DETACH";
        break;
    default :
        out << "UNKNOWN_CALL: " << ul_reason_for_call;
    }
    out << " lpReserved=" << lpReserved << endl;
    return TRUE;
}
--
Tomi Maila
0 Kudos
Message 6 of 12
(10,497 Views)

hi there,

i get

Load VI to memory             :   DLL_PROCESS_ATTACH lpReserved=00000000
Remove VI from memory   :   DLL_PROCESS_DETACH lpReserved=00000000

i attached my vi and the dll sources (LV 6.0, MS VC++ 6.0)

Best regards
chris

CL(A)Dly bending G-Force with LabVIEW

famous last words: "oh my god, it is full of stars!"
0 Kudos
Message 7 of 12
(10,494 Views)
Starting with next LabVIEW release, the Call Library Node interface is exposing a set of functions to allow the user to easily configure calls to methods that may be used to initialize and cleanup Call Library Node instance data. The callbacks that will be configurable are for DLL reserve, unreserve, and abort processing. The reserve would be used in a manner consistent with the Windows process attach. Unreserve is consistent with the Windows process detach and so on.

Note: After the abort procedure is called for processing an abort, the unreserve procedure will also be called.

Each callback passes a single parameter which is a pointer sized allocation for use at the DLLs discretion - it can be typecast and used as an integer, it can be typecast and used to store a pointer to an allocated structure, ... These distinct calls allow the user to configure calls to user written procedures to manage Call Library Node instance data in a consistent manner across platforms.

And, yes. The callbacks may be configured to call LabVIEW VIs in a Labview built DLL.
Message 8 of 12
(10,490 Views)
Thanks Ken,

The new feature sounds great! It seems it was your first post to the forums, I gave you 5 stars, congrats! Can you still explain in which situations Win LV 8.0  calls process attach, process detach, thread attach and thread detach.

Tomi
--
Tomi Maila
0 Kudos
Message 9 of 12
(10,483 Views)
AFAIK, when and how to call WinMain is up to the operating system, only indirectly to LV.
Apparently, PROCESS_ATTACH is called when the DLL is loaded (i.e. at vi loading), probably by calling LoadLibrary, as stressed by chrisger.
However, the sequence you recorded is puzzling: I wouldn't expect more than one PROCESS_DETACH without a corresponding PROCESS_ATTACH.
Paolo
-------------------
LV 7.1, 2011, 2017, 2019, 2021
0 Kudos
Message 10 of 12
(10,477 Views)