Reyneke Posted April 12, 2011 Report Share Posted April 12, 2011 (edited) Hey there. I have a little problem. I am using the Kithara Software Realtime Suite to connect a set of EtherCAT Slaves to an EtherCAT master. So far everything has been fine, but at the moment, I am stuck. Since Kithara uses a combined structure to transmit the data from the slaves and back, I needed to write a wrapper DLL. It looks like this: [code#ifndef ___ETHERCATLV_H#define ___ETHERCATLV_H/* Call Library source file */#include <extcode.h>#include <api\_ethercat.h>#include <dos.h>#include <stdio.h>#include <stdlib.h>#include <time.h>#include <string.h>/* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */#include "lv_prolog.h"/* Typedefs */typedef struct { int32_t vendorId; int32_t productId; int32_t revision; int32_t serial; LStrHandle group; LStrHandle image; LStrHandle order; LStrHandle name; int32_t objCount; } TD1;typedef struct { int32_t objType; LStrHandle name; int32_t bitLength; int32_t index; int32_t syncIndex; int32_t varCount; } TD2;typedef struct { int32_t objType; LStrHandle name; int32_t dataType; int32_t bitLength; int32_t subIndex; } TD3;#include "lv_epilog.h"extern "C" {_declspec(dllexport) uint32_t KS_queryEcatSlaveInfoLV(uint32_t hSlave, int32_t indexObject, int32_t indexVariable, TD1 *pSlaveInfo, TD2 *pDataObjInfo, TD3 *pDataVarInfo, int32_t flags);}_declspec(dllexport) uint32_t KS_queryEcatSlaveInfoLV(uint32_t hSlave, int32_t indexObject, int32_t indexVariable, TD1 *pSlaveInfo, TD2 *pDataObjInfo, TD3 *pDataVarInfo, int32_t flags){ KSEcatDataVarInfo* dataVarInfo_; KSEcatDataObjInfo* dataObjInfo_; KSEcatSlaveInfo* slaveInfo_; Error error = KS_OK; uint size = 0; error = KS_queryEcatSlaveInfo((KSHandle) hSlave, &slaveInfo_, flags); if (error == KS_OK) { pSlaveInfo->vendorId = slaveInfo_->vendorId; pSlaveInfo->productId = slaveInfo_->productId; pSlaveInfo->revision = slaveInfo_->revision; pSlaveInfo->serial = slaveInfo_->serial; size = strlen(slaveInfo_->group); memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size; size = strlen(slaveInfo_->image); memcpy(LStrBuf(*pSlaveInfo->image), slaveInfo_->image, size); LStrLen(*pSlaveInfo->image) = size; size = strlen(slaveInfo_->order); memcpy(LStrBuf(*pSlaveInfo->order), slaveInfo_->order, size); LStrLen(*pSlaveInfo->order) = size; size = strlen(slaveInfo_->name); memcpy(LStrBuf(*pSlaveInfo->name), slaveInfo_->name, size); LStrLen(*pSlaveInfo->name) = size; pSlaveInfo->objCount = slaveInfo_->objCount; size = strlen(slaveInfo_->objs[indexObject]->name); memcpy(LStrBuf(*pDataObjInfo->name), slaveInfo_->objs[indexObject]->name, size); LStrLen(*pDataObjInfo->name) = size; pDataObjInfo->bitLength = slaveInfo_->objs[indexObject]->bitLength; pDataObjInfo->index = slaveInfo_->objs[indexObject]->index; pDataObjInfo->syncIndex = slaveInfo_->objs[indexObject]->syncIndex; pDataObjInfo->varCount = slaveInfo_->objs[indexObject]->varCount; pDataVarInfo->objType = slaveInfo_->objs[indexObject]->vars[indexVariable]->objType; size = strlen(slaveInfo_->objs[indexObject]->vars[indexVariable]->name); memcpy(LStrBuf(*pDataVarInfo->name), slaveInfo_->objs[indexObject]->vars[indexVariable]->name, size); LStrLen(*pDataVarInfo->name) = size; pDataVarInfo->dataType = slaveInfo_->objs[indexObject]->vars[indexVariable]->dataType; pDataVarInfo->bitLength = slaveInfo_->objs[indexObject]->vars[indexVariable]->bitLength; pDataVarInfo->subIndex = slaveInfo_->objs[indexObject]->vars[indexVariable]->subIndex; } return error;}#endif // ___ETHERCATLV_H][/code] Now, here is my problem: The VI crashes everytime when I execute the VI. Sometimes its just gone without an explanation. I think it is an error in the declaration of the VI itself, but I am not sure. Can you help me? Thanks for taking your time - Reyneke Edited April 12, 2011 by Reyneke Quote Link to comment
Rolf Kalbermatter Posted April 12, 2011 Report Share Posted April 12, 2011 size = strlen(slaveInfo_->group); memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size; size = strlen(slaveInfo_->image); memcpy(LStrBuf(*pSlaveInfo->image), slaveInfo_->image, size); LStrLen(*pSlaveInfo->image) = size; size = strlen(slaveInfo_->order); memcpy(LStrBuf(*pSlaveInfo->order), slaveInfo_->order, size); LStrLen(*pSlaveInfo->order) = size; size = strlen(slaveInfo_->name); memcpy(LStrBuf(*pSlaveInfo->name), slaveInfo_->name, size); LStrLen(*pSlaveInfo->name) = size; What makes you think these handles have been allocated so you can simply access their data pointer to write data into????? Quote Link to comment
Reyneke Posted April 12, 2011 Author Report Share Posted April 12, 2011 What makes you think these handles have been allocated so you can simply access their data pointer to write data into????? To be honest, nothing ... However since I am new to LabView/unexperienced in it: What can I do to make it better? Where can I check that? I am not sure if a simple malloc() will work. Quote Link to comment
Reyneke Posted April 12, 2011 Author Report Share Posted April 12, 2011 Okay. I have allocated memory for slaveInfo, dataObjInfo and dataVarInfo via malloc now and freed it after using it, but it still crashes. Quote Link to comment
Reyneke Posted April 12, 2011 Author Report Share Posted April 12, 2011 Okay, that was a devil in the detail. Well, in fact it was a devil nestled in old habits. I initialised the CIN, calling this function, this way: All integers with a value of zero and all strings with a value of ... "NULL". Why yes, I am a C-programmer and new to LabView? Why do you ask? Now the function itself runs fine. The Indicators on mz VI show me the value I requested, all thats left is to find the reason for the 1097 Error, that pops up when the function finishes and the CIN is left again. Can you give me a hint? Quote Link to comment
Rolf Kalbermatter Posted April 12, 2011 Report Share Posted April 12, 2011 Okay, that was a devil in the detail. Well, in fact it was a devil nestled in old habits. I initialised the CIN, calling this function, this way: All integers with a value of zero and all strings with a value of ... "NULL". Why yes, I am a C-programmer and new to LabView? Why do you ask? Now the function itself runs fine. The Indicators on mz VI show me the value I requested, all thats left is to find the reason for the 1097 Error, that pops up when the function finishes and the CIN is left again. Can you give me a hint? First I didn't even catch that you were not even allocating memory for the slaveInfo, etc. local variables. That is quite an error to do for a C programmer! It should have been the first thing to check before you even post! But I was really referring to the embedded string handles in the structures you pass from LabVIEW. Unless you go to the length to explicitly fill those elements with actual initialized arrays of sufficient length in the diagram, those string handles will be empty handles when arriving in your function, and an empty array in LabVIEW is simply a NULL handle for performance reasons. No use to allocate a handle (two pointers) that can only hold the 0 integer to indicate that no data follows. LabVIEW Handles are NOT simple memory pointers. They are really pointers to pointers to memory blocks AND need to be allocated and destroyed with LabVIEW memory manager function calls, as described in the External Code Reference Manual, since LabVIEW will use the same functions to handle those handles. If you just plainly go and use malloc(), you confuse the memory manager in very serious ways that will sooner than later result in unrecoverable errors. Look into NumericArrayResize(), which is the recommended way, or the low level functions DSNewHandle(), DSSetHandleSize(), etc. Instead of: size = strlen(slaveInfo_->group);memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size);LStrLen(*pSlaveInfo->group) = size; you will want to do something like: size = strlen(slaveInfo_->group);err = NumericArrayResize(uB, 1, (UHandle*)&pSlaveInfo->group, size);if (!err){ memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size;} And a nitpick really but it's not a CIN. As far as I know the newest LabVIEW platform versions (64 bit Windows for instance) doesn't even support creating CINs. Instead you create a shared library (DLL) and import it using the Call Library Node (CLN) on all platforms. Quote Link to comment
Reyneke Posted April 13, 2011 Author Report Share Posted April 13, 2011 First I didn't even catch that you were not even allocating memory for the slaveInfo, etc. local variables. That is quite an error to do for a C programmer! It should have been the first thing to check before you even post! Well, slaveInfo_ is self initialising. In fact if you call it via malloc or something else, chances are it is going to fail and cause an exception. But I was really referring to the embedded string handles in the structures you pass from LabVIEW. Unless you go to the length to explicitly fill those elements with actual initialized arrays of sufficient length in the diagram, those string handles will be empty handles when arriving in your function, and an empty array in LabVIEW is simply a NULL handle for performance reasons. No use to allocate a handle (two pointers) that can only hold the 0 integer to indicate that no data follows. LabVIEW Handles are NOT simple memory pointers. They are really pointers to pointers to memory blocks AND need to be allocated and destroyed with LabVIEW memory manager function calls, as described in the External Code Reference Manual, since LabVIEW will use the same functions to handle those handles. If you just plainly go and use malloc(), you confuse the memory manager in very serious ways that will sooner than later result in unrecoverable errors. Look into NumericArrayResize(), which is the recommended way, or the low level functions DSNewHandle(), DSSetHandleSize(), etc. Ahhh, I see. Now it all makes a lot more sense. Thank you for clearing that error up, Rolf. I changed the code accordingly and now it looks like this: #ifndef ___ETHERCATLV_H#define ___ETHERCATLV_H/* Call Library source file */#include <extcode.h>#include <api\_ethercat.h>#include <string.h>/* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */#include "lv_prolog.h"/* Typedefs */#if MSWin && ProcessorType != kX64 #pragma pack(push,1) #endif typedef struct { int32_t vendorId; int32_t productId; int32_t revision; int32_t serial; LStrHandle group; LStrHandle image; LStrHandle order; LStrHandle name; int32_t objCount; } TD1;typedef struct { int32_t objType; LStrHandle name; int32_t bitLength; int32_t index; int32_t syncIndex; int32_t varCount; } TD2;typedef struct { int32_t objType; LStrHandle name; int32_t dataType; int32_t bitLength; int32_t subIndex; } TD3; #if MSWin && ProcessorType != kX64 #pragma pack(pop) #endif #include "lv_epilog.h"extern "C" {_declspec(dllexport) uint32_t KS_queryEcatSlaveInfoLV(uint32_t hSlave, int32_t indexObject, int32_t indexVariable, TD1 *pSlaveInfo, TD2 *pDataObjInfo, TD3 *pDataVarInfo, int32_t flags);}_declspec(dllexport) uint32_t KS_queryEcatSlaveInfoLV(uint32_t hSlave, int32_t indexObject, int32_t indexVariable, TD1 *pSlaveInfo, TD2 *pDataObjInfo, TD3 *pDataVarInfo, int32_t flags){ KSEcatSlaveInfo* slaveInfo_; Error error = KS_OK; uint size = 0; MgErr err; error = KS_queryEcatSlaveInfo((KSHandle) hSlave, &slaveInfo_, flags); if (error == KS_OK) { pSlaveInfo->vendorId = slaveInfo_->vendorId; pSlaveInfo->productId = slaveInfo_->productId; pSlaveInfo->revision = slaveInfo_->revision; pSlaveInfo->serial = slaveInfo_->serial; size = strlen(slaveInfo_->group); err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->group, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size; } size = strlen(slaveInfo_->image); err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->image, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->image), slaveInfo_->image, size); LStrLen(*pSlaveInfo->image) = size; } size = strlen(slaveInfo_->order); err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->order, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->order), slaveInfo_->order, size); LStrLen(*pSlaveInfo->order) = size; } size = strlen(slaveInfo_->name); err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->name, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->name), slaveInfo_->name, size); LStrLen(*pSlaveInfo->name) = size; } pSlaveInfo->objCount = slaveInfo_->objCount; size = strlen(slaveInfo_->objs[indexObject]->name); err = NumericArrayResize(uB, 1, (UHandle *)&pDataObjInfo->name, size); if (!err) { memcpy(LStrBuf(*pDataObjInfo->name), slaveInfo_->objs[indexObject]->name, size); LStrLen(*pDataObjInfo->name) = size; } pDataObjInfo->bitLength = slaveInfo_->objs[indexObject]->bitLength; pDataObjInfo->index = slaveInfo_->objs[indexObject]->index; pDataObjInfo->syncIndex = slaveInfo_->objs[indexObject]->syncIndex; pDataObjInfo->varCount = slaveInfo_->objs[indexObject]->varCount; pDataVarInfo->objType = slaveInfo_->objs[indexObject]->vars[indexVariable]->objType; size = strlen(slaveInfo_->objs[indexObject]->vars[indexVariable]->name); err = NumericArrayResize(uB, 1, (UHandle *)&pDataVarInfo->name, size); if (!err) { memcpy(LStrBuf(*pDataVarInfo->name), slaveInfo_->objs[indexObject]->vars[indexVariable]->name, size); LStrLen(*pDataVarInfo->name) = size; } pDataVarInfo->dataType = slaveInfo_->objs[indexObject]->vars[indexVariable]->dataType; pDataVarInfo->bitLength = slaveInfo_->objs[indexObject]->vars[indexVariable]->bitLength; pDataVarInfo->subIndex = slaveInfo_->objs[indexObject]->vars[indexVariable]->subIndex; } return error;}#endif // ___ETHERCATLV_H Unluckily, I still get an 1097 error, when the project exits. I have included the VI belonging to the code above in this file and I still can't find a possible reason where the message stems from. The VI itself works fine. All data requested is fine, the only thing bugging me (so to speak) is the 1097 error message that appears each time the CLN exits. Do you have an idea, where it might come from? And a nitpick really but it's not a CIN. As far as I know the newest LabVIEW platform versions (64 bit Windows for instance) doesn't even support creating CINs. Instead you create a shared library (DLL) and import it using the Call Library Node (CLN) on all platforms. Good point. For a moment I was going to use CINs, but then remembered the warning I heard about CINs being out of date and so used CLN's. Quote Link to comment
Rolf Kalbermatter Posted April 14, 2011 Report Share Posted April 14, 2011 Well, slaveInfo_ is self initialising. In fact if you call it via malloc or something else, chances are it is going to fail and cause an exception. In that case you are leaking that memory with every call???? A few more notes: You are indexing into the object and variable tables with passed in parameters without verifying that those indices are valid in the constraints of the provided data. Quote Link to comment
Reyneke Posted April 17, 2011 Author Report Share Posted April 17, 2011 In that case you are leaking that memory with every call???? Good point. That might be, but unluckly KSEcatSlaveInfo*is initialized by the driver, so its out of my hand to do that. About the parameters: It took me a few tries to realize, that the driver does not return a NULL if a string is missing and not a "\0" either. In fact it returns something erroneus, that looks like a string to me without an '0'. I managed to catch that by counting the length of the string and replacing it with an informational message (called this, because PDOs and SDOs can not include a value bz design, so that it is not an error) if the length is zero. However that brought up two interesting new things: There is something added to it, which seems completely random. At the moment catching the exception looks like this: if (strlen(slaveInfo_->group) <= 0) memcpy((char *) slaveInfo_->group, temp, strlen(temp)); size = strlen(slaveInfo_->group); err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->group, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size; }[\code]while temp is: const char * temp = "nothing specified \0";Still that error remains ... Do I need to check the int values also/ And if yes, how? I mean null in int just means zero. Quote Link to comment
Reyneke Posted April 19, 2011 Author Report Share Posted April 19, 2011 Ooookay, I added more changes. Now the DLL looks like this: #ifndef ___ETHERCATLV_H#define ___ETHERCATLV_H/* Call Library source file */#include "extcode.h"/* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */#include "lv_prolog.h"#include <api\_ethercat.h>#include <string.h>/* Typedefs */#if MSWin && ProcessorType != kX64 #pragma pack(push,1) #endif typedef struct { int32_t vendorId; int32_t productId; int32_t revision; int32_t serial; LStrHandle group; LStrHandle image; LStrHandle order; LStrHandle name; int32_t objCount; } TD1;typedef struct { int32_t objType; LStrHandle name; int32_t bitLength; int32_t index; int32_t syncIndex; int32_t varCount; } TD2;typedef struct { int32_t objType; LStrHandle name; int32_t dataType; int32_t bitLength; int32_t subIndex; } TD3; #if MSWin && ProcessorType != kX64 #pragma pack(pop) #endif #include "lv_epilog.h"extern "C" {_declspec(dllexport) uint32_t KS_queryEcatSlaveInfoLV(uint32_t hSlave, int32_t indexObject, int32_t indexVariable, TD1 *pSlaveInfo, TD2 *pDataObjInfo, TD3 *pDataVarInfo, int32_t flags);}_declspec(dllexport) uint32_t KS_queryEcatSlaveInfoLV(uint32_t hSlave, int32_t indexObject, int32_t indexVariable, TD1 *pSlaveInfo, TD2 *pDataObjInfo, TD3 *pDataVarInfo, int32_t flags){ KSEcatSlaveInfo* slaveInfo_; Error error = KS_OK; uint size = 0; MgErr err; const char* temp = "-none specified-\0"; error = KS_queryEcatSlaveInfo((KSHandle) hSlave, &slaveInfo_, flags); if (error == KS_OK) { pSlaveInfo->vendorId = slaveInfo_->vendorId; pSlaveInfo->productId = slaveInfo_->productId; pSlaveInfo->revision = slaveInfo_->revision; pSlaveInfo->serial = slaveInfo_->serial; if (indexObject > slaveInfo_->objCount) indexObject = 0; if (indexVariable > slaveInfo_->objs[indexObject]->varCount) indexVariable = 0; if (strlen(slaveInfo_->group) <= 0) { memcpy((char *) slaveInfo_->group, temp, strlen(temp) + 1); //slaveInfo_->group = temp; } size = strlen(slaveInfo_->group) + 1; err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->group, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size; } if (strlen(slaveInfo_->image) <= 0) { memcpy((char *) slaveInfo_->image, temp, strlen(temp) + 1); //slaveInfo_->image = temp; } size = strlen(slaveInfo_->image) + 1; err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->image, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->image), slaveInfo_->image, size + 1); LStrLen(*pSlaveInfo->image) = size; } if (strlen(slaveInfo_->order) <= 0) { memcpy((char *) slaveInfo_->order, temp, strlen(temp) + 1); //slaveInfo_->order = temp; } size = strlen(slaveInfo_->order + 1); err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->order, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->order), slaveInfo_->order, size); LStrLen(*pSlaveInfo->order) = size; } if (strlen(slaveInfo_->name) <= 0) { memcpy((char *) slaveInfo_->name, temp, strlen(temp) + 1); //slaveInfo_->name = temp; } size = strlen(slaveInfo_->name) + 1; err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->name, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->name), slaveInfo_->name, size); LStrLen(*pSlaveInfo->name) = size; } pSlaveInfo->objCount = slaveInfo_->objCount; pDataObjInfo->objType = slaveInfo_->objs[indexObject]->objType; if (strlen(slaveInfo_->objs[indexObject]->name) <= 0) memcpy((char *)slaveInfo_->objs[indexObject]->name, temp, strlen(temp) + 1); size = strlen(slaveInfo_->objs[indexObject]->name) + 1; err = NumericArrayResize(uB, 1, (UHandle *)&pDataObjInfo->name, size); if (!err) { memcpy(LStrBuf(*pDataObjInfo->name), slaveInfo_->objs[indexObject]->name, size); LStrLen(*pDataObjInfo->name) = size; } pDataObjInfo->bitLength = slaveInfo_->objs[indexObject]->bitLength; pDataObjInfo->index = slaveInfo_->objs[indexObject]->index; pDataObjInfo->syncIndex = slaveInfo_->objs[indexObject]->syncIndex; pDataObjInfo->varCount = slaveInfo_->objs[indexObject]->varCount; pDataVarInfo->objType = slaveInfo_->objs[indexObject]->vars[indexVariable]->objType; if (strlen(slaveInfo_->objs[indexObject]->vars[indexVariable]->name) <= 0) memcpy((char *)slaveInfo_->objs[indexObject]->vars[indexVariable]->name, temp, strlen(temp) + 1); size = strlen(slaveInfo_->objs[indexObject]->vars[indexVariable]->name) + 1; err = NumericArrayResize(uB, 1, (UHandle *)&pDataVarInfo->name, size); if (!err) { memcpy(LStrBuf(*pDataVarInfo->name), slaveInfo_->objs[indexObject]->vars[indexVariable]->name, size); LStrLen(*pDataVarInfo->name) = size; } pDataVarInfo->dataType = slaveInfo_->objs[indexObject]->vars[indexVariable]->dataType; pDataVarInfo->bitLength = slaveInfo_->objs[indexObject]->vars[indexVariable]->bitLength; pDataVarInfo->subIndex = slaveInfo_->objs[indexObject]->vars[indexVariable]->subIndex; } return error;}#endif // ___ETHERCATLV_H It works fine, all variables are within specific parameters, it even checks if variables have been assigned or not and yet, still, I get an 1097 memory error everytime the program runs. I think it might be another memory problem, as sometimes the "-none specified-\0" message lacks one or two characters and yet I can"t really explain why. Quote Link to comment
Rolf Kalbermatter Posted April 19, 2011 Report Share Posted April 19, 2011 Ooookay, I added more changes. Now the DLL looks like this: if (indexObject > slaveInfo_->objCount) indexObject = 0; if (indexVariable > slaveInfo_->objs[indexObject]->varCount) indexVariable = 0; Are you really sure there will be always at least one object? Why not coarse the index to the lower and upper end instead of always setting them to 0 when out of bound? If obj/varCount is 0 you still will index the first element later on!!!!! if (strlen(slaveInfo_->group) <= 0) { memcpy((char *) slaveInfo_->group, temp, strlen(temp) + 1); //slaveInfo_->group = temp; } Are you sure slaveInfo_->group is never a NULL pointer? And if that is the case, are you sure it points to a buffer long enough, that can be overwritten with your string? And the overwriting as well as the commented out code have another potential problem. Since the slaveinfo structure seems to be returned by the function and probably isn't allocated as you otherwise would need to deallocate it at the end, it is likely static memory or at least a static global pointer and messing around with its contents could then have fatal consequences for the driver implementation in the DLL. size = strlen(slaveInfo_->group) + 1; err = NumericArrayResize(uB, 1, (UHandle *)&pSlaveInfo->group, size); if (!err) { memcpy(LStrBuf(*pSlaveInfo->group), slaveInfo_->group, size); LStrLen(*pSlaveInfo->group) = size; } You don't need the + 1 since LabVIEW string handles don't need to be zero terminated and shouldn't contain a possible zero termination char in their length count. Many potential trouble and I'm sure there could be more as I do not know the entire API. The API structure is a very nasty implementation and IMHO worthless. This is fine for internal function parameters but not for an API that can be accessed by other units. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.