ni.com is currently undergoing scheduled maintenance.

Some services may be unavailable at this time. Please contact us for help or try again later.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

"Problems developing a vision algorithm shared library (.so) on the NI Linux Real-Time x64 platform."

Solved!
Go to solution

谢谢 rolfk,这真的很有帮助——彻底解开了很多疑惑。

你说得对,我和克劳德在错误的道路上耗费了太长时间。我们浪费了大量时间去追查“两个库实例”、SDK 版本不匹配、ABI 不兼容等等问题。结果发现真正的问题要根本得多:  LabVIEW IMAQ 引用句柄和图像指针根本不是一回事 。

如果其他人也遇到类似情况,以下是我们发现问题的简要总结:

  1. 最初我将 Image 参数设置为“适应类型,按值处理”——这会传递一些内部 LabVIEW 包装结构,而不是实际的 Image* 指针。

  2. 每次 NI Vision 调用(imaqThreshold、imaqGetImageType、imaqGetImageSize 等)均失败,错误代码为 -1074396120(“不是图像”)。

  3. 经过一系列测试(全局变量检查以确认单个 .so 实例、内存诊断、dlopen 比较),我发现将参数更改为“数值、无符号指针大小的整数、传递值”后,一切都正常了——imaqGetImageType 返回 0 (U8),imaqThreshold 返回 1,并且图像被正确二值化。

但根据你的解释,我现在明白了,这种“有效”的方法可能并未得到官方支持或任何文档记录。将 IMAQ 引用句柄作为指针大小的整数传递恰好有效,这很可能只是一个实现细节,未来版本可能会失效。

0 Kudos
Message 11 of 13
(73 Views)

Here is the exact solution to my problem:

change 

ddddd212_0-1775870283847.png

 

to 

ddddd212_1-1775870322663.png

 

There's a code I'm sending out as well for those who need it

0 Kudos
Message 12 of 13
(65 Views)

@ddddd212 wrote:

 

You're right, Claude and I spent far too much time on the wrong track. We wasted a lot of time tracking down "two library instances," SDK version mismatches, ABI incompatibility, and so on. It turned out the real problem was much more fundamental: the LabVIEW IMAQ reference handle and the image pointer were not the same thing at all.

If anyone else is experiencing something similar, here's a brief summary of what we found:

Initially, I set the Image parameter to "Accommodate type, handle by value"—this was passing some internal LabVIEW wrapper structure instead of the actual Image* pointer.

Every NI Vision call (imaqThreshold, imaqGetImageType, imaqGetImageSize, etc.) failed with error code -1074396120 ("Not an image").

After a series of tests (global variable checks to confirm a single .so instance, memory diagnostics, dlopen comparisons), I found that changing the parameters to "numeric, integer the size of an unsigned pointer, pass value" made everything work correctly—imaqGetImageType returned 0 (U8), imaqThreshold returned 1, and the image was correctly binarized.

However, based on your explanation, I now understand that this "effective" method may not be officially supported or documented. Passing the IMAQ reference handle as an integer the size of a pointer happens to work, which is likely just an implementation detail and may fail in future versions.


Yes, that's a trick that COULD work. LabVIEW refnums always wrap an actual C object of some sort. This can be a pointer to an internal memory struct as with the FileRefnum for instance which simply contains the necessary data such as the underlaying file descriptor or handle to operate on the file. The actual pointer corresponds to the File* datatype documented in the External Code Reference Manual. This datatype is also incomplete as it only documents the pointer but not what it contains. Under Windows it happens to simply be the file HANDLE, under Linux it is the int file descriptor. But this is private information that NI never documented and therefore they are free to change it whenever the need arises. Relying on such findings in anything but experimental software is a very shaky thing to do.

 

A VISA Refnum for instance resolves to the underlaying ViSession datatype from the VISA API. This is not well known but actually sort of documented in some instrument drivers NI released in the past. For VISA Refnums at least it is rather unlikely to ever change unless the entire VISA API is going to change, but as it is not just an NI internal standard but one they pushed into a semi-independent consortium (on which NI still holds a strong control), that is very unlikely to happen before the end of computing on this world. 😁

 

Your find that the converted IMAQ Refnum seems to resolve to the Image* pointer is therefore not so surprising, but I'm not aware of any NI Toolkit or library they ever released, including some experimental examples maybe, where they would have openly used that and by doing so kind of documented this as a valid use. The first danger is that this could change with any version of LabVIEW or IMAQ Vision. The second that the values are indeed equal but that there needs more work to be done such as acquiring a certain mutex or whatever before you are allowed to safely treat this as an Image* pointer. It may work now, and suddenly fail when you do multiple images at the same time, or your controller has a higher CPU load than usual. Yes I'm fantasizing here a little, but each of these and quite a few more are possible problems when you use such undocumented features.

 

Is NI going to change this soon? Not very likely but there are no guarantees, not even if you go back to every version of LabVIEW and NI IMAQ Vision and verify that it always has been like this and still is until the latest version. It's a complicated enough change that they would never do this simply to make anyone fail. They are not that pity nor do they care about someone using an undocumented feature. But there might be technical reasons when an engineer finds that there should be a change and even without intending it, this may break this feature. As it is undocumented, it may never be tested in any unit tests during any build release cycle of either LabVIEW or IMAQ Vision and only be found if NI somewhere still makes use of it internally. And if it then breaks for you, you have no ground to stand on. Reporting it as bug is more likely than not simply wasted time, as breaking an undocumented feature is generally not considered a bug but simply bad luck for whoever did spend time to find that feature and decided to use it. Unless you are part of a company that NI/Emerson sells many million bucks of stuff to every year, nobody is going to even look into such things.

 

Last but not least, what did you gain? You can now pass an IMAQ refnum to the imaq.. functions in nivision.so. Great! But for every imagXYZ function in that shared library there is also a similar LV_XYZ function in it that does basically the same thing and corresponds to a LabVIEW VI on the palette. They are not all exact matches since the imaq.. functions were meant to be called from C in LabWindows/CVI. There are some functions that were split into different functions that the LV functions solve all in the same. So you now can basically do in your shared library what you could do otherwise on the LabVIEW diagram. You have not won anything more. The Image* datatype is still an unfinished datatype that you can not look into since that is the intended thing from NI, to avoid having callers depend on library internal knowledge that may and certainly will change between IMAQ Vision versions.

 

So what remains?

 

1) You identified an imaq.. function that is not available on the LabVIEW IMAQ Vision palette and want to use that. That's a possibility but seems unlikely.

 

2) Your image analysis/manipulation algorithm is very advanced, super secret and multi trillion dollar worth and you want to protect it by putting it into a shared library instead of implementing it on the LabVIEW diagram. This is security through obscurity. If your algorithm is really that advanced and important, it will be hacked the moment you release it to anyone outside your company no matter if you put it into a password protected LabVIEW diagram or into a compiled shared library. Disassembly is a real thing, very easy to do for experienced hackers and impossible to prevent. Your compiled shared library is just a very minor obfuscation step compared to a LabVIEW diagram, even if you don't even use a password on the LabVIEW diagram.

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