LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

about call C++ dll

I find that opencv tool can deal with this question。

0 Kudos
Message 11 of 14
(793 Views)

Here's an example (and just now tested) use case.

The function I shared before is modified to directly link to the labview.lib file, and to use snprintf over sprintf to satisfy a security error.

 

// dllmain.cpp : Defines the entry point for the DLL application.
#include "extcode.h"
#include <iostream>

#define DllExport __declspec( dllexport )

LStrHandle CreateLabVIEWString(std::string message) {
    // Calculate needed memory space
    int stringLength = message.length();
    const unsigned int memSize = sizeof(int32) + stringLength * sizeof(uChar);

    LStrHandle handle = reinterpret_cast<LStrHandle>(DSNewHandle(memSize));
    // Empties the buffer
    memset(LStrBuf(*handle), '\0', memSize);
    // Add data
    snprintf(reinterpret_cast<char*>(LStrBuf(*handle)), memSize, message.c_str());
    // Inform the LabVIEW string handle about the size of the string
    LStrLen(*handle) = stringLength;

    return handle;
}
extern "C" {
    DllExport void getAString(LStrHandle* handle) {
        std::string msg = "This is the string I want to send to LabVIEW...";
        *handle = CreateLabVIEWString(msg);
    }
}

 

Example_VI.png

cbutcher_0-1614919451752.png

 


GCentral
0 Kudos
Message 12 of 14
(788 Views)

@yanzhanglin wrote:

Z(0T3460@TWC5]0(NAN7UPY.png

 my C++ code is this ,but it return no correct


You definitely show not enough to let us make sense of this. As it looks to me, it is completely wrong. This is standard memory management and you need to understand the implications of who allocates what. If you do not want to pass in a string pointer and preallocate it in the caller, you can pass in a LabVIEW string handle and let the function do it. But you need to do it right.

 

#include "extcode.h"

MgErr ConvertStringToLStrHandle(string s, LStrHandle str)
{
    MgErr err = mgArgErr;
    if (str)
    {
        MgErr err = ::NumericArrayResize(uB, 1, (UHandle*)&str, s.length());
        if (!err)
        {
            ::MoveBlock(s.c_str(), LHStrBuf(str), s.length())
            LStrLen(*str) = (int32)s.length();
        }
    }
    return err;
}

 

This is not tested and I have not done proper C++ casting in this code, but for the rest it should be ok.

 

NumericArrayResize() is a convinience function and despite that it is really meant to handle array allocations, it also can be used for string handle allocations/resizing, since a LabVIEW string is in fact simply a 1D array of bytes.

 

If you insist on using lower level functions you have to also account for the len integer in front of the data:

 

#include "extcode.h"

MgErr ConvertStringToLStrHandle(string s, LStrHandle str)
{
    MgErr err = mgArgErr;
    if (str)
    {
        MgErr err = ::DSSetHandleSize(str, sizeof(int32) + s.length());
        if (!err)
        {
            ::MoveBlock(s.c_str(), LHStrBuf(str), s.length());
            LStrLen(*str) = (int32)s.length();
        }
    }
    return err;
}

 

You can also pass in a LabVIEW handle by reference and then things get a bit more tricky:

 

#include "extcode.h"

MgErr ConvertStringToLStrHandle(string s, LStrHandle *str)
{
    MgErr err = mgArgErr;
    if (str)
    {
        if (!*str)
        {
            // Got an empty handle passed as NULL handle, allocate a new one
            *str = ::DSNewHandle(sizeof(int32) + s.length());
            if (!*str)
                return mFullErr;
        }
        else
        {
            err = ::DSSetHandleSize(*str, sizeof(int32) + s.length());
        }
        if (!err)
        {
            ::MoveBlock(s.c_str(), LHStrBuf(*str), s.length());
            LStrLen(**str) = (int32)s.length();
        }
    }
    return err;
}

 

This is where NumericArrayResize() really starts to be more convenient:

 

#include "extcode.h"

MgErr ConvertStringToLStrHandle(string s, LStrHandle *str)
{
    MgErr err = ::NumericArrayResize(uB, 1, (UHandle*)str, s.length());
    if (!err)
    {
        ::MoveBlock(s.c_str(), LHStrBuf(*str), s.length());
        LStrLen(**str) = (int32)s.length();
    }
    return err;
}

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 13 of 14
(772 Views)

@cbutcher wrote:

Here's an example (and just now tested) use case.

The function I shared before is modified to directly link to the labview.lib file, and to use snprintf over sprintf to satisfy a security error.

 

// dllmain.cpp : Defines the entry point for the DLL application.
#include "extcode.h"
#include <iostream>

#define DllExport __declspec( dllexport )

LStrHandle CreateLabVIEWString(std::string message) {
    // Calculate needed memory space
    int stringLength = message.length();
    const unsigned int memSize = sizeof(int32) + stringLength * sizeof(uChar);

    LStrHandle handle = reinterpret_cast<LStrHandle>(DSNewHandle(memSize));
    // Empties the buffer
    memset(LStrBuf(*handle), '\0', memSize);
    // Add data
    snprintf(reinterpret_cast<char*>(LStrBuf(*handle)), memSize, message.c_str());
    // Inform the LabVIEW string handle about the size of the string
    LStrLen(*handle) = stringLength;

    return handle;
}
extern "C" {
    DllExport void getAString(LStrHandle* handle) {
        std::string msg = "This is the string I want to send to LabVIEW...";
        *handle = CreateLabVIEWString(msg);
    }
}

 

Example_VI.png


Strictly speaking this is not right. If someone goes into your diagram and wires a non-empty string to the left side of your string parameter you are leaking that handle each time it is called!

 

Of course you could argue that this is a bit like the patient going to the doctor and complaining about that it hurts when he pushes on a certain point on his body and the doctor answering "Then don't do that!" but I'm sure you can see the problem. 😂

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 14 of 14
(764 Views)