Jump to content

Recommended Posts

I am trying to pass a 2d array initialized with large data in my c dll to labview, but no matter what I only get a pointer to the array at best shot. I want to get the array as return type from the function I get  when I use labview shared library wizard.
 

#include<stdlib.h>
#include<stdio.h>
#include<stdint.h>
__declspec(dllexport) int* get_results(){

int *array;
array=malloc(3*3*sizeof(int8_t));
int a=0;
for (int y=0;y<3;y++){
    for(int x=0;x<3;x++){
        int index=y*3+x;
        array[index]=a;
        a++;
    }
}

return array;

}

for this I get "get results.vi" which after running it I only get a negative number.
and for this one :

__declspec(dllexport) int get_results(){

int *array;
array=malloc(3*3*sizeof(int8_t));
int a=0;
for (int y=0;y<3;y++){
    for(int x=0;x<3;x++){
        int index=y*3+x;
        array[index]=a;
        a++;
    }
}

return *array;

}

I got get results1.vi which I get nothing after running the vi.
I don't know how should I make the function or dll that I get the array from the vi that shared library wizard gives me
please help me

get results1.vi get results.vi

Link to comment

I think what you want is MoveBlock. This is basically a function that takes a pointer and returns the actual data at the pointer. I don't deal with DLL calling often, and I have a hard time figuring out things so I might be wrong.  You may want to do some research into it.  Here are a few links.

Link to comment
3 hours ago, alireza m said:

thanks for your opinion but I want to find a way to pass the actual array not some pointer to it

LabVIEW arrays are NOT C array pointers. You can NOT allocate an array with malloc() and hope to return that to LabVIEW in a way that LabVIEW knows that this is an array. You could return it as pointer sized opaque pointer but LabVIEW could not do anything with it directly.

You have two options:

1) Preallocate an array in LabVIEW with the necessary size and pass it to the function. Configure the according pointer to pass the array as C data pointer.

Important: The array MUST be allocated on the LabVIEW diagram. You can NOT use C Library memory management functions to allocate, resize and free memory buffers that you want LabVIEW to use on the diagram!

#inclide <stdint.h>
  
void GetArray(int32_t *arr, size_t dim_x, size_t dim_y)
{
	for (size_t x; x < dim_x; x++)
    {
	    for (size_t y; y < dim_y; y++)
        { 
             arr[x + y * dim_x] = 0;
        }
    }
}

2) Use a native LabVIEW array.

#include "extcode.h"

#include "lv_prolog.h"
typedef struct
{
    int32_t dims[2];
    int32_t elms[];
} Int2DArrRec, *Int2DArrPtr, **Int2DArrHdl;
#include "lv_epilog.h"

MgErr GetArray(Int2DArrHdl *arr, size_t dim_x, size_t dim_y)
{
    MgErr err = NumericArrayResize(iL, 2, (UHandle*)arr, dim_x * dim_y);
    if (!err)
    {
        int32_t *ptr = (**arr)->elms;
        for (size_t x; x < dim_x; x++)
        {
            for (size_t y; y < dim_y; y++)
            { 
                ptr[x + y * dim_x] = 0;
            }
        }
        (**arr)->dims[0] = dom_x;
        (**arr)->dims[1] = dom_x;
    }
    return err;
}

 

Edited by Rolf Kalbermatter
Link to comment

thanks, but I used your code and in shared library wizard I got this error :

_declspec(dllexport) MgErr GetArray(Int2DArrHdl* arr, size_t dim_x, size_t dim_y);

Undefined symbols can prevent the wizard from recognizing functions and parameters. To correct this problem, check the header file to determine if you must add preprocessor definitions. Click the Back button to return to the previous page of the wizard to add a preprocessor definitionsl (for example, "NIAPI_stdcall = __stdcall" or "NIAPIDefined = 1").


The following header file was not found in the specified header file or one of the referenced header files:
-  extcode.h
-  lv_prolog.h
-  lv_epilog.h

To fix, click the Back button to go to the previous page and add the header file path to the Include Paths list.
 

after all this I think the problem is mostly using shared library wizard and the best choice is using call library function node

 

can I allocate an array in c and after initializing it copy its data to an array  like here to pass the array data?
by the way my data is large like 3000*3000 and I might get access violation error running my dll vi.
 

#include "extcode.h"

_declspec(dllexport) void ARRAY2D(double *array,
                                  int array_length_row,
                                  int array_length_col);
_declspec(dllexport) void ARRAY2D(double *array,
                                  int array_length_row,
                                  int array_length_col)
{
  int i, j;

  for(i = 0; i < array_length_row; i++)
  {
    for(j = 0; j < array_length_col; j++)
    {
      array[(i * array_length_col) + j] = array[(i * array_length_col) + j] *
                                          array[(i * array_length_col) + j];
    }
  }
}
Edited by alireza m
Link to comment

If you use LabVIEW native datatypes, the Import Shared Library Wizard is NOT the right tool to use. Generally speaking if you are not able to configure the Call Library Node yourself correctly, use of the Import Shared Library Wizard is simply a way to setup your code for failure. There is absolutely no way that an automated tool could create always correct code from a C header file alone, except for really trivial APIs. The C syntax is to ambiguous to describe all aspects of an API and it does not at all describe memory management issues for any parameters that are more complex than scalars.

Generally speaking, you either have a non-LabVIEW specific DLL that hopefully uses generic C data types as parameters and is not trying to pass dynamically allocated memory buffers to the caller, or you start with a LabVIEW VI, configure a Call Library Node and connect native LabVIEW datatypes to it, configure the according parameters to Adapt To Type, right click on the Call Library Node and select "Create c. file" and then use the generated prototype and fill in the function body with what you want to implement in the C function.

For the code example 2) I provided you have to:

1) NOT use the Import Library Wizard, it can NOT deal with the complex types that LabVIEW native datatypes are.

2) configure your C compiler to look in the cintools directory inside the LabVIEW directory for header files

3) Configure a Call Library Node yourself with three parameters:

        1) Adapt to Type, pass Pointers to Handles and wiring an according 2D LabVIEW array of Int32 to it

        2) Integer, Pointer sized, Pass by Value

        3) Integer, Pointer sized, Pass by Value

 

As to your code, yes you can do it like that. "#include extcode.h" is however useless, there is nothing in your code that would need that header file.

You then create a Call Library Node and configure it to have these parameters:

        1) Array, int32, 2 dimensions, Pass as Array Data Pointer

        2) Integer, int32, Pass by Value

        3) Integer, int32, Pass by Value

Make sure to always use "Initialize Array" on the diagram to allocate a 2D array with the same sizes as what you pass to the function in the 2nd and 3rd parameter and wire that array to the 1st parameter!!!! If the array is not allocated or allocated smaller than what you tell the function to fill in, you just created a "crash your computer" program! It may usually not crash (right away), but it will corrupt memory and eventually your LabVIEW program will crash, eat your harddrive or do something else that is undesirable and there is nobody to blame for that but yourself.

And about the used datatypes: While int is always a 32-bit integer for all platforms on which LabVIEW can run and use of it in your C code is therefore not really a problem, other basic C datatypes such as long are not the same size on some of the platforms. Therefore it is useful to use explicitly sized datatypes such as int32_t for parameters that interface with the LabVIEW diagram. LabVIEW is very strictly typed and always uses explicitly sized datatype, the only exception are the two pointer sized integer datatypes, but they only exist in the Call Library Node, never on the diagram.

Edited by Rolf Kalbermatter
  • Like 1
Link to comment
Just now, alireza m said:

thank you so much. and something else is bothering me. I have to make a dll out of the .c file I get by "create .c file"?

The file you get with "Create c. file" is just a function prototype with an empty function. You can of course turn that into a DLL but it won't do anything useful. You can fill in the function with some useful code and then it is a good starting point for your DLL.

My usual working method is slightly different. I use the "create c. file" function to create a file containing the matching function prototype, then copy this prototype from that file into the real project C file that I use to implement my DLL. But in most cases I don't even need that intermediate C file as I'm usually able to create the correct function prototype myself.

  • Thanks 1
Link to comment

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...

Important Information

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