Jump to content

Rolf Kalbermatter

Members
  • Posts

    3,901
  • Joined

  • Last visited

  • Days Won

    269

Everything posted by Rolf Kalbermatter

  1. That would work, but you also need to wire the nBufSize parameter. Can you guess with what value?
  2. I think the separate compiled code is only a by-product. It could have been done even without the VIs having been set to use separate compiled code. In the worst case the VIs would have been compiled the first time you open a project that uses them. So what? Inconvenient? I don't think so, at least not nearly as much as having to always chase the right drivers.
  3. Definitely agree that it should have been done like that many moons ago already. But it was in a way maybe easier to do it like that as there was limited testing needed and maybe there was also a bit of an intention behind it as if you wanted to use new hardware you had to install the new driver and that made also a new IDE version necessary if the previous one was to old. So a bit of a hidden upgrade nudge. Now with the new NI structure where the different software departments are very much decoupled and independent from each other it proved to be an unmanageable modus operandi. It's not feasible anymore to have to pester DAQmx (and cRIO and System Control and, and, and) folks to release a new version of their software simply because there is a new LabVIEW version.
  4. Unless your data strream consists of very large packets in the beginning, there is absolutely no guarantee that your PlayM4 stream already has enough data the first time around to produce a valid JPG image. It is very well possible that you must feed it with a dozen or more compressed data packages before it is able to even create a single full frame image. And until then the GetJPEG function will likely return false as it has no data to return yet. Once it has enough data stored internally it may return a valid image but not in the buffer size that you passed to the IntputData method. That image will typically require quite a bit more bytes. What I did mean to do is to call GetJPEG() first with a null pointer for the data and 0 for nBufSize and then use the return value of pJPEGSize to allocate a big enough buffer to call the function again This may or may not work (again!) depending on the PlayM4 API functionality. Currently you are anyhow creating a crasho-mobil (again!!) since you pass in an empty byte array and have not configured that parameter to have a Minumum Size that is nBufSize. So you tell the functon: Look I have here a buffer and it contains at least nBufSize bytes, but you really pass in a buffer that contains 0 bytes. Kabom! Crash! as soon as the function has something to write into that buffer and tries to do that, since you told it that there is a buffer of a certain size it can write into. I have no idea what you try to say with this. If you mean to create an array constant with that size, you can but it is useless. Either you use Initialize Array to create an array of the necessary size or you configure in the Call Library Node the Minimum Size parameter of your array to be that of one of the other parameters, (why not use the nBufSize parameter here, as it very accidentally tells the function what size the byte array parameter has been allocated to). I mean it is just an idea, but it would seem logical to me. 😃
  5. You definitely will need the PlayM4_InputData(). Somehow you must provide the decoder with the continuous stream of data packages. Then it may or may not choke on the NULL HWND and it may or may not store the decoded data somewhere internal in the port and if it doesn't choke on the NULL HWND AND does store the decoded data somewhere in the port, you can call the PlayM4_GetJPEG() data. But of course you need to provide a large enough buffer to it, so MAYBE you can first call it with a NULL pJpeg and nBufSize = 0 and use the pJpegSize to call it again with a properly allocated buffer. Lots of may and may not and the only one who can find out about that is you!
  6. Not sure why you respond in this thread with this. But yes that has always been like this. Except that the locking goes away if you remove the reference to the class, or library from any but one of the targets.
  7. What's the calling convention you set for these functions? And no, you can calculate that multiplication by hand, your hand calculator, an abacus or explicitly in LabVIEW and wire that result to the Call Library Node. It does NOT matter. But you will want to store that "port" value somewhere (maybe in a shift register, it's just a suggestion) to use when sending the actual data packages to the decoder.
  8. NO! Configure that parameter simply as Array, Element Type U8, Pass as Data Pointer! But seriously you should first learn more C before trying to go further on this! And there is no need to convert the byte array into a string to determine its length to pass to the DLL function. There is also an Array Size function, you know?
  9. I'm saying you send NOTHING there. This is the definition of the user event datatype and what you "send" there into that cluster makes absolutely no difference. You could just as well leave the entire Bundle by Name away. What is important is the data type that the LVEventData element defines, nothing else. And this data type must at ALL times match the data type setup on the C side for the user event data structure or VERY BAD things will happen.
  10. Of course, and where did you get that header from? It can never compile in any C compiler that I know of. But it would help if you use generally accepted terms in your communication. A CRASH is something that occurs AFTER you have COMPILED and LINKED your application and start it. I usually means that your process dies with or without an according error message. What you encountered was a COMPILE ERROR since the compiler could not understand the code statement.
  11. That makes doubly no sense. Or you need to specify which dwDatatype you mean. First as dadreamer already explained and I tried to explain at least twice before. Second,which dwDataType are you talking about? The dwDataType in the callback routine is not something you should change at all. It is what the SDK driver returns to you and that's it. That is the definition of a callback, it is called by the other software component with values that you should use, not manipulate unless the callback function documentation states explicitly that you are expected to return some data in one or more of the passed in buffers.
  12. And as you can see in the code, the error value is 5000 + whatever the NET_DVR_GetLastError() returned. Now you go into the SDK documentation and read what error 17 means. So yes the function thinks that one of the parameters is not valid. The callback function pointer can't really be it, neither can it say anything about the callback data parameter, so that leaves only the session handle. I have no idea why it thinks that is invalid.
  13. The exact value of the session variable is not to be interpreted in any way other than what the API documentation states. And in there it says: It's a bit unclear thanks to the non-native people who wrote that SDK. But I interprete that as follows. This specifically means that a value of 0 should be also valid. Typically these "handles" are simply an index into an API private array of structures that contain the actual data to manage the session/connection/resource. Just changing the definition of the Call Library Node is NOT sufficient. You also need to change the C code to actually return a specific value!!!!! When you define the Call Library node for SetCbState() to return a value, the implementation of that funciton in your C code must explicitly return a value or the Call Library Node will simply return a random value (more specifically: whatever the function left dangling in the eax register of the CPU).
  14. Did you change the function to actually return a value? In the last code you posted the SetCbState() function returns void. That means you can configure the Call Library Node to return an integer value, but what it will return is random data, or more precisely whatever the function was last using the eax register for. Since it is declared to have a void return value, the compiler does not make sure to return anything meaningful in there. I would change the actual InstallCallback function as follows: //If the above if condition does not occur, the LVUserEventRef here does not take a value. typedef BOOL(__stdcall* Type_SetStandardDataCallBack)(LONG lRealHandle, void(CALLBACK* fStdDataCallBack) (LONG lRealHandle, DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize, DWORD dwUser), DWORD dwUser); extern "C" __declspec(dllexport) MgErr __cdecl InstallStandardCallback(LONG lRealHandle, LVUserEventRef * refnum) { HMODULE hDLL = LoadLibraryW(L"HCNetSDK.dll"); if (hDLL) { Type_SetStandardDataCallBack installFunc = (Type_SetStandardDataCallBack)GetProcAddress(hDLL, "NET_DVR_SetStandardDataCallBack"); if (installFunc) { BOOL retval; if (refnum && *refnum) retval = installFunc(lRealHandle, DataCallBack, (DWORD)(*refnum)); else retval = installFunc(lRealHandle, NULL, 0); if (retval) return mgNoErr; else return 5000 + NET_DVR_GetLastError(); } FreeLibrary(hDLL); } return mgNotSupported; }
  15. I had some suspicion in this direction. 😃 Anyone doing this for money would either have given up long ago because the available budget was running out very quickly or having been shot by the client for not delivering on his promises. 😆 But it doesn't mean that it makes the work more feasible.
  16. I'm sorry if I sound harsh. We have a Dutch saying here. Translated it says about this: I felt it is time to be a little harsh here. alvise is strampling and barely keeping his head above the water and he has not even started to realize that his ordeal is far from over. Making the callback function work is only a first step on a very long path to get the actual video data into an image format that he can use in LabVIEW!
  17. It's something not just not everyone can do, but very few who work with LabVIEW. Usually people choose to work with LabVIEW because they are not programmers but want to solve something. Writing DLLs is a lot more complicated, interfacing them to LabVIEW somewhat more. Doing Video handling even just in LabVIEW alone is pretty hard, and trying to combine all these things together is VERY hard. As to the quote statement, there are two ways to start a project when someone asks you to do it. You make an estimate of the required time, slap some security margin on top of that and multiply it with your hourly rate and quote that to the client. Or you start programming and charge him by the hour as you go. This last version more often than not ends in the situation where your customer wants to see results before paying even one dollar more and you are still far from having anything to show him. So it is a very bad model to work with, but if the problem is hard and your experience with it limited you are in no position to make a good estimate, so all you can do in good faith is to refuse the invitation to submit a tender bid. Even I would have to think twice about taking on such a contract and I'm absolutely not kidding here. As explained before, once the callback is working you still have NOTHING. The data is compressed and decompressing video data in an efficient manner is never easy even if you can use ready made libraries that handle your specific compression format perfectly. As it is we don't even know exactly how that video stream is compressed nor how the individual bits are packaged into it.
  18. Yes I know! But I give up here. I'm probably too old to be able to deal with this.
  19. Communication with you is sometimes rather difficult. The code he shows is different to the original code I posted many many moons ago, long before the post with the new code that I referenced now (and which he shows). So he asked if you had applied that change too, as otherwise calling the InstallStandardCallback function with a NotANumber refnum would have zero effect. And you answer "No, no changes have been made here". It shows me two things: - You don't remember what you did a few days ago - You really don't understand what you are doing here I wonder if you know how to do C source code level debugging? You can have the Visual Studio Debugger show where in the code you are, when building the DLL in Debug mode (which as you had to find out earlier can have certain implications while compiling but it can help to verify what you are doing on the C code level). It's tricky to get Visual Studio do the right thing and it's even trickier to not get yourself tied up with legs behind your neck and arms under you ass when trying to do that with callback code, but it can be done. But I hesitate to mention this option as I'm not sure you will be able to get yourself untied after venturing down this path. 😆 More likely than not you will get yourself many times in a deadlock situation where you should acknowledge something in LabVIEW to be able to proceed but can't because the execution flow is stopped in Visual Studio and LabVIEW is blocked by that, but when you continue code execution in Visual Studio it goes way to fast to let you do that acknowledgment in LabVIEW. Only solution at that point: Ctrl+Alt+Del, look for your LabVIEW and Visual Studio process in the task list and kill them. Hopefully you saved all your work before starting your test, because otherwise it's gone. It's tedious and frustrating to have to work like that, but for me I could never get DLL code properly working without at least some source level code debugging in C. That is because I do not just want a DLL not to crash. Once its execution doesn't crash you are not even half done. You need to make sure that it does not sneakily overwrite buffers anyways somewhere. If you don't or can't do that debugging, you are only creating a huge liability for yourself and whoever you give this code later on to use it. Such buffer overwrites may not crash your system now, but they do destroy data in memory. If this is measurement data for your multi-million $ experiment, some driver structures that under extreme situations might cause actual physical or integral damage to your hardware, or just by sheer luck only destroy unused memory somewhere, you don't know. But you can be of one thing sure, it won't always do the same thing. Depending on memory layout of your machine, which can depend on many things such as what other applications are running alongside or which OS revision you are running (yes even a minor OS update could have a huge impact on that), your "harmless" buffer overwrite suddenly turns into a 7 fanged dragon that consistently crashes your process and possibly even others in very nasty ways. Or it silently destroys your experiment measurement data and makes your whole program more than utterly useless. One test I do is to run such code on at least 3 different LabVIEW version and if it is by any means multiplatform, also on all the possible platforms like Windows, Linux and Mac. This catches most such bugs in one way or the other at some point. Yes it is a lot of work, and yes it is tedious but the chance to release a shared library that corrupts memory is simply to big otherwise.
  20. Go back to this post and look at the code and the explanation I gave there! If you want to stay with analogies, it could be also the headlights of the train that is running to roll over you. 😆
  21. This type of error is very quickly the difference between a crashing monster and a well behaving application. There is no LabVIEW who can save you from this. It is YOU who has to make sure that what you write in the external code, matches exactly what you tell LabVIEW to expect. It must be able to trust you blindly on this or your library is nothing more than a bunch of crashing dummies. If you can't make sure of that because you obviously don't understand the actual implications and/or easily forget about them after they have been explained to you a few posts earlier, then you are truly playing with fire in trying to create such a library. Seriously! That are the statements I love in every problem description. Very precise and to the point, NOT! How does it look when you conclude it is not read? Does just the array get empty data? Do the other values such as lRealHandle turn to show a different value too? And which one? Right now it is like I show you a picture of a nice car (your image shows that there is actually data) and then tell you he doesn't sometimes work. Can you help me? Who could except someone with clairvoyant abilities? Does it start? Does it suddenly stop? Are you sure there is gas in the tank? Do any lights in the dashboard light up? You see what I'm saying?
  22. Why did you post a picture where it was U8 and then use U32 in your Vi??????
  23. It doesn't return "anything". That indicator only gets written to in the LV User Event case. As long as you do not see such an event in the Event Inspector Window it simply means that the LVPostUserEvent() function either was not called or not with the correct user event refnum that your user event structure is registered to.
  24. Could it be that he simply did not activate the button again but left it pressed as it was? That state is only send on state change of the button, not because LabVIEW magically doesn't know that it should call that event case again to send the True state to the DLL.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.