Jump to content

candidus

Members
  • Posts

    109
  • Joined

  • Last visited

  • Days Won

    11

Posts posted by candidus

  1. This is a prime example of digging around in LabVIEW and finding fool's gold instead of actual gold.

     

    Well, that's why I asked about it. Thank you! Nevertheless I think there should be done something about it:

    Either implement the primitive properly or remove it entirely. Since it was never released this should break nobody's code. :D

  2. Are your examples meant to involve by-value or by-reference objects? I can see how they work for by-reference objects, but they wouldn’t work with by-value objects (since your making copies at every wire branch).

    I want them to work with both. Do I have to use references inside my delegates or is bundling/unbundling inside IPE structures enough?. There's so much to learn... :lightbulb:

  3. To be Devil’s advocate, isn’t the need to put the word “unrelated” in there a bit of a problem? I’m not familiar with OOP interfaces, but isn’t the idea that interfaces are different ways of treating the same object? Representing a single object as a collection of different objects with no connections between them might work sometimes, but the instant you have a relationship (say, Child2 needs to call a method on Child1 in order to execute “Child2Info.vi”) then you have a problem.

    I think we're talking about different kinds of (un)relationship. I thought primarily of unrelated interface hierarchies. In languages like C# or Java you can inherit from a single concrete or abstract class just like in LV, but also from multiple interfaces. In LV you have just single inheritance, so the only way to implement multiple interfaces is aggregation.

    That doesn't mean that the aggregated objects are necessarily unrelated: They can be just delegates forwarding the method calls to the object that aggregates them. Here is an example:

    ImplementerWithDelegatedInterfaces.zip

    But you're right, in my first example they are unrelated. It's probably bad OO style :)

    An experimental modification:

    Just great!

    So a reference version would look like this.

    post-941-0-43473300-1336347935_thumb.png

    Seems that we have to implement AddRef() and Release() now ;)

  4. I had a similar issue. The following worked for me:

    Any DLL built by LV exports the a function

    long __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);

    I thought that function would tell me what's wrong and called it at the beginning of my C code:

    char errStr[128];

    LVDLLStatus(errStr, 127, NULL);

    It didn't tell me anything but it fixed the issue! I assume that the LV runtime was not fully initialized before this call but that's just a guess.

  5. Does anyone remember the object model of COM aka ActiveX? There's a base interface, IUnknown, that any COM object has to implement. IUnknown provides three methods:

    - QueryInterface()

    - AddRef()

    - Release()

    Interface hierarchies use single inheritance, but a COM object can implement multiple interface hierarchies. It can either implement them directly or aggregate other COM objects that implement them and expose these aggregated object via QueryInterface() to clients. Thus a single COM object can provide access to multiple and maybe unrelated interfaces.

    OK, that's COM. Let's get back to LV now. If we want interface inheritance in LV we have almost the same restrictions as above. We have single inheritance and if we want to support multiple unrelated interfaces we have to use aggregation. The COM object model can help us here. Let's take a look at IUnknown again. AddRef() and Release() are methods for reference counting and we all know that references are evil (well, not always, I know:-) so these won't be of much help.

    The interesting part is QueryInerface(). We can implement something in LV that very closely resembles that method. Imagine a dynamic dispatch VI that takes a LV object constant representing an interface, queries an internal repository of aggregates and returns the object that implements the desired interface. We don't even need to cast the result because we can use thralling.

    We can even relax the rules of the COM object model:

    The aggregated objects don't have to follow that model. They can be implemented using interface separation, the can be compound objects implementing QueryInterface() themselves but they can also be just LV objects with arbitrary bases.

    Here is an example implementation. Enjoy!

    candidus

    InterfaceProvider.zip

    • Like 1
  6. I don't really know how they are related as I don't have access to the .Net source code. If I were to guess I would say they might be siblings, but they're actually interfaces--not concrete classes--and they may not be in any sort of inheritance hierarchy.

    You might be able to get information about their relationship without source code. Use IL disassembler (ildasm.exe) that ships with the .NET SDK.

  7. You have to configure the Call Library Function Node according to the prototype of your C function, all argument types and positions have to match.

    Here is a modified version of your VI with the (hopefully) correctly configured Call Library Function Node:

    test_dll.vi

    Note: A function argument that returns data must be a pointer. If an argument returns a string you have to allocate memory before: You can initialize an array of U8 and use that as string argument.

  8. I'm currently writing an XML library based on OpenG Data and String functions. I use the functions Format Variant into String and Scan Variant from String to do String<->Variant conversions. It works but I stumbled upon problems that required me to modify these VIs:

    - Scan Variant from String can change the data type of the original Variant. If I format any integer type the output Variant alway contains an I64, any floating point type becomes an EXT, any complex type becomes a CXT. This was not acceptable for me so I fixed it

    - Both VIs have problems with locale decimal points if no format string is specified. I added a control Default Floating Point Format to specify a default format string for floating point numbers.

    StringToVariant.zip

    I'd like to contribute my modifications, IMHO they could be useful for others, too. :)

  9. The configuration of the Call Library Function Node is wrong. Take a look at the header file of your DLL. The required function prototype is:

    void __stdcall NIDAQ_Wave_Get_070528(char DAQPort[], double rate,

    long samplesPerChannel, long inputTerminalConfiguration, LVBoolean *Result,

    double *Amplitude, double *Frequency, char ErrorMsg[], long *len);

    Your Call Library Function Node is actually configured for:

    int32_t __stdcall NIDAQ_Wave_Get_070528(void *input terminal configuration, int32_t Amplitude,

    int32_t Frequency, CStr DAQ Port, int32_t samples per channel, int32_t rate);

  10. It definitely works. I played around with the different LW API functions. You can even use the system() function that is part of the ANSI C library. My example command was:

    char *cmd="cmd /k echo \"Hello world\"";

    Here are the options:

    // Does not wait for the executable to finish.

    LaunchExecutable(cmd);

    // Waits for the executable to finish. Even part of the ANSI C standard.

    system(cmd);

    // Runs the executable...

    int procHandle = 0;

    LaunchExecutableEx(cmd, LE_SHOWNORMAL, &procHandle);

    // .. and enters a loop (timing 0.1s) that waits for the executable to finish.

    while(!ExecutableHasTerminated(procHandle))

    {

    Delay(0.1);

    }

    There's really no problem here, perhaps there was one years ago in the stone age of programming, I have no clue :-)

    And why not, I can create a DLL also...or convince them to migrate to a real programing language ;-)

    That may be an even better idea ;-)

    • Like 1
  11. Here is a quote from the CVi documentation:

    LaunchExecutable

    int LaunchExecutable (char filename[]);

    Purpose

    Starts running a program and returns without waiting for the program to exit.

    Note If you want to wait for the program to exit, use the system function in the ANSI C Library.

    The program must be an actual executable; that is, you cannot launch commands intrinsic to a command interpreter.

    The executable can be either a DOS or Windows executable, including *.exe, *.com, *.bat, and *.pif files.

    .exe, .com, and .bat DOS programs use the settings in _default.pif (in the Windows directory) when running. You can change their priority, display options, and so on., by editing _default.pif or by creating another .pif file. Refer to www.msdn.com for information about creating and editing .pif files.

    If you need to execute a command built into command.com such as copy, dir, and others, you can call LaunchExecutable with the following command:

    command.com /C DosCommand args

    where DosCommand is the shell command you want to execute. For example, the following command string copies file.tmp from the temp directory to the tmp directory:

    command.com /C copy c:\\temp\\file.tmp c:\\tmp

    Note If you want to monitor whether the launched executable has terminated, use LaunchExecutableEx.

    In other words: It should work...

    • Like 1
  12. I also wonder why LV installs xalan but doesn't provide an API to it...

    There's a project called LabXML (labxml.sourceforge.net, LGPL license). It is based on the opensource library libxml2 and supports XSL transformation. I usually use it when I have to work with stylesheets. Besides .NET, on Windows the MSXML 4.0 COM library is also an option.

  13. I have figured something out: That sucks...

    Joking aside: It seems we can obtain the data type information, but we have to use LVClass references and property nodes to get the ancestor hierarchy. I created a small ClassInfo library and an example:

    ClassPrivateData.zip

    However, there's another way to get the data of the current class only:

    post-15449-0-67283600-1327524708_thumb.p

    It uses the VI "Get Mutation History.vi" from vi.lib to get the class private data type as Variant.

    That's all far away from being an OpenG-ready solution but at least it seems to work in the runtime engine of LV2010.

    I had problems with the runtime engine of LV2009, the VI executes but becomes broken after it has finished.

  14. Thank you, I understand better now. But even the "Edit Tree Items.Add Item" method of the LV tree control has an input to specify "Child Position". I wonder why it is unused in this Tree Control API. I would create a derived class to override the default behavior but unfortunately that is impossible: The necessary properties aren't exposed in the API. Seems that I have to modify the classes and maintain my own copy... :(

×
×
  • Create New...

Important Information

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