03-04-2021 09:46 PM
I find that opencv tool can deal with this question。
03-04-2021 10:44 PM
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);
}
}
03-06-2021 04:17 AM - edited 03-06-2021 04:48 AM
@yanzhanglin wrote:
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;
}
03-06-2021 04:33 AM - edited 03-06-2021 04:35 AM
@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); } }
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. 😂