จากตอนที่แล้ว ได้พูกถึง C++ DLL and C-Warpper for LabVIEW ตอนนี้มาพูดถึงอะไรที่เกี่ยวกับพื้นฐานที่จำเป็นกันบ้างเนื่องจากการมองเห็นตัวแปรของ LabVIEW โดยเฉพาะ Pointer มีความแตกต่างอย่างมากเมื่อเทียบกับ C/C++
การพัฒนา Library ด้วย C/C++ สำหรับ LabVIEW จึงเป็นเรื่องที่ท้าทาย และเป็นปัญหาที่พบเห็นกันโดยทั่วไปในเว็บบอร์ดของ Developers
ถึงแม้ว่า LabVIEW มีฟังก์ชั่นรองรับเรื่อง Memory Management อยู่แล้วมากมาย และออกแบบมาเพื่อการพัฒนาโดยเฉพาะ แต่นั่นดูเหมือน
จะเป็นเรื่องที่ไกลตัวจากกลุ่ม Programmer สาย C/C++ เพราะคำอธิบายของแต่ละฟังก์ชั่นส่วนมากจะไม่ชัดเจน หรืออาจจะยากต่อการตีความในหลายมุมมอง
(ปัญหา นี้เกิดขึ้นกับตัวผมเองเช่นกัน และต้องใช้เวลาในการทำความเข้าใจในเชิงลึกว่าด้วย LabVIEW Memory Managment)
เพื่อเป็นการเลี่ยงการลืมของตัวเอง และคาดหวังว่าจะเป็นประโยชน์กับใครสักคนที่จะผ่านเข้ามาในบอร์ดนี้ จึงนำ Code ที่ได้เขียนขึ้นเพื่อการศึกษามาลงไว้ที่นี่
(หัวข้อนี้ เหมาะสำหรับ Programmer ที่เจาะ LabVIEW เชิงลึกเท่านั้น แต่ไม่ได้หมายความว่า "ห้ามมือใหม่อ่าน")ในที่นี้จะขอยกตัวอย่างการจัดการกับ Array of Cluster of Int32 ซึ่งมีรูปแบบดังนี้:#include "lv_prolog.h"
typedef struct {
int32_t Element;
} MyCluster;
typedef struct {
int32_t dimSize;
MyCluster Cluster[1];
} MyArray;
typedef MyArray **MyArrayHdl;
#include "lv_epilog.h"
คำว่า "Array of Cluster of Int32" หมายถึง มีข้อมูลชนิด Int32 อยู่ใน Cluster และ Cluster อยู่ใน Arrayโดยธรรมชาติของ LabVIEW เข้าถึง Memory ที่ไม่ใช้ตัวแปรชนิด Scalar (เช่น Array หรือ Memory Block) จะอ้างผ่าน Pointer-to-Array/Memory-Handle หรือ Pointer-to-Pointer-to-Array/Memory นั่นเอง ในที่นี้ structure คือ Memory ดังนั้น จึงใช้ typedef MyArray **MyArrayHdl เพื่อใช้ MyArrayHdl ในการอ้างถึง MyArray SDW_DLL_EXPORT int TestFunction(MyArrayHdl arrayIn, MyArrayHdl arrayOut)
{
int32_t sum = 0;
if (arrayIn!=NULL && arrayOut !=NULL) // empty arrays will have a NULL handle
{
for (int32_t ii = 0; ii < (*arrayIn)->dimSize; ii++)
{
(*arrayOut)->Cluster[ii].Element = 2 * (*arrayIn)->Cluster[ii].Element;
sum += (*arrayIn)->Cluster[ii].Element;
(*arrayIn)->Cluster[ii].Element += 1;
DbgPrintf("array[%i]=%i\r\n", ii, (*arrayIn)->Cluster[ii].Element);
}
DbgPrintf("\r\nSum of the array is %i\r\n", sum);
}
else
{
DbgPrintf("ERROR: NULL Array!");
}
return(sum);
}
จากโปรแกรม จะเห็นได้ว่า การเข้าถึง member variables ใน structure จะอ้างผ่าน (*arrayIn/Out)-> ความหมายคือ อ้างถึงตัว Pointer ที่ชี้ไปยัง member variables นั่นเองโปรแกรมมีการเข้าถึง Array/Memoryต่ำแหน่งต่างๆ แล้ว Array/Memory นั้นมาจากไหน?
กลับมาดูที่ vi จะได้คำตอบในทันที
ว่า...Array/Memory มาจาก "Array-of-Cluster In" นั่นเอง นั่นหมายความว่า Array-of-Cluster In จะต้องถูก define ก่อนเรียกใช้ TestFunction นั่นเอง
พิจารณาต่อ โปรแกรมมีการเขียนค่าลงไปยัง arrayOut (array of cluster Out) แล้ว Array/Memory ของ arrayOut มาจากไหน?
ย้อนกลับไปดูที่ vi อีกที ชัดเจนว่า arrayOut ถูก define พร้อมกับ arrayIn นั่นเอง
จะเห็นได้ว่าใน C ไม่มีการขอ/คืน หน่วยความจำ นั่นคือเราประกาศขอใช้หน่วยความจำจาก vi นั่นเอง
ในตอนต่อไป ค่อยมาดูกันว่า ในกรณีที่ต้องการขอ/คืนหน่วยความจำจาก C โดยตรง จะมีวิธีการ แบบไหน อย่างไร