2

I have a DLL file that is written in C. I tried to use it in managed code but some how my function is not working properly. Here is the C code.

int preProcessImagesC (char *p_trainingFilePath,
                       char **p_vecImageFilesOrDirs);  

This function is working fine.

Managed code :

unsafe private static extern int preProcessImagesC(
    //Works perfact 
    String p_trainingFilePath,
    //char** thise parameter is taking junk values , String Array is not working
    [MarshalAs(UnmanagedType.SafeArray)] ref String[] p_vecImageFilesOrDirs);

Only first parameter is working properly. What should I use for char **p_vecImageFilesOrDirs parameter in managed code. Please help me to write compatible code in C#.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
  • 2
    It is not possible to answer this question with the information here. We don't know the flow of data. What exactly is `p_vecImageFilesOrDirs`? Is it an array of strings, passed in to the native code? Or is is a pointer to string, passed by reference, to allow the native code to return a single string to the caller? Or is it something else? Likewise what is `p_trainingFilePath`? In or out? And what about calling convention? Where do you specify that? And why use unsafe? Finally, please format the code. The code looks like it has just been puked in there! Lay it out neatly. – David Heffernan Apr 10 '13 at 09:30
  • p_vecImageFilesOrDirs: [Input parameter] An array of strings (null-terminated strings) of all the image files or directories that contain the input images that are to be processed. Calling function: int iResult = preProcessImagesC(p_trainingFilePath, ref p_vecImageFilesOrDirs, ); – user2181754 Apr 10 '13 at 12:01
  • The function will ignore any directories that does not exist, and will return -1 if none of the directories/files exist. – user2181754 Apr 10 '13 at 12:08
  • Sounds like MD's answer is correct – David Heffernan Apr 10 '13 at 12:13
  • How does the callee obtain the length of the array? – David Heffernan Apr 10 '13 at 15:40

2 Answers2

4

Did you try:

private static extern int preProcessImagesC(
    string p_trainingFilePath,
    string[] p_vecImageFilesOrDirs
);

The marshaller automatically uses:

[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPTStr)]

that is what you need.

You should be careful about this, because there is no way that your unmanaged code can determine the actual size of the passed array. You have to pass the real size of the array to the unmanaged function as another parameter, or use a fixed size in both places.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
  • Thanks for the replay. I have used String[] but string[] p_vecImageFilesOrDirs is not working so I used ref Byte[] p_vecImageFilesOrDirs but still it works for the one item in array need solution for multiple items. – user2181754 Apr 10 '13 at 13:05
  • +1 The code in this answer works correctly if @user's first comment to the question is accurate. – David Heffernan Apr 10 '13 at 15:45
  • @user2181754 It is strange that this works for a single string but not for a string array. Can you test it with a simple function? Try with a single string array parameter. – Mohammad Dehghan Apr 11 '13 at 21:02
  • 1
    @MD.Unicorn I have tested it. The code works perfectly. The explanation is that user2181754 has described the interface correctly. But a DLL that receives an array of null-terminated strings, will receive the data correctly with the code in this answer. The question is wrong. – David Heffernan Apr 12 '13 at 19:34
  • unless user2181754's DLL requires the array of strings to be terminated (like ANSI C requires of main's argv) with a pointer to NULL, to tell it that it's at the end of the list? – sjcaged Jun 27 '14 at 08:57
  • @sjcaged That's also an option to mark the end of the array. We can add a `null` at the end of the managed array. – Mohammad Dehghan Jun 29 '14 at 07:39
-2

A string is already an array of characters.
Thus you should be fine with

ref String p_vecImageFilesOrDirs

You are currently copying a reference to array of array of characters.

weismat
  • 7,195
  • 3
  • 43
  • 58