Eric Toorner
Eric Toorner

Reputation: 55

C++ dll pass array to C#

I have to pass from my C++ dll array to the C# program. Here is the C++ code:

 __declspec(dllexport) std::vector<std::string> __stdcall 
    getFilesByDirs
    (
        string directory, 
        std::string fileFilter, 
        bool recursively = true
    )
{
    int __ID = 0;
    std::vector<std::string> filesArray;

    if (recursively)
        getFilesByDirs(directory, fileFilter, false);

    directory += "\\";

    WIN32_FIND_DATAA FindFileData;
    HANDLE hFind = INVALID_HANDLE_VALUE;

    std::string filter = directory + (recursively ? "*" : fileFilter);

    hFind = FindFirstFileA(filter.c_str(), &FindFileData);

    if (hFind == INVALID_HANDLE_VALUE)
    {
        return filesArray;
    }
    else
    {
        if (!recursively)
        {
            if(isGoodForUs(directory + std::string(FindFileData.cFileName))) 
            {
                filesArray[__ID] = directory + std::string(FindFileData.cFileName);
                __ID ++;
            }
        }

        while (FindNextFileA(hFind, &FindFileData) != 0)
        {
            if (!recursively)
            {
                if(!isGoodForUs(directory + std::string(FindFileData.cFileName))) continue;
                filesArray[__ID] = directory + std::string(FindFileData.cFileName);
            }
            else
            {
                if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)>0 && FindFileData.cFileName[0]!='.')
                {
                    if(!isGoodForUs(directory + std::string(FindFileData.cFileName))) continue;
                    getFilesByDirs(directory + std::string(FindFileData.cFileName), fileFilter);
                }
            }
            __ID ++;
        }

        DWORD dwError = GetLastError();
        FindClose(hFind);
    }

    return filesArray;
}

As you can see, there is a function that scanning for files by type. It's saved in the string array and returning out.

Now, here is the C# code:

[DllImport(@"files.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr getFilesByDirs(string path, string exns, bool rec=true);

and then i am calling to this method:

IntPtr a = getFilesByDirs("C:\\", "*.docx");

The problem is that nothing pass to my C# program from the Dll. Anyone can help with my issue?

Upvotes: 3

Views: 1840

Answers (1)

Will Custode
Will Custode

Reputation: 4614

You need to return them not as a vector but as a primitive type, such as a char**. The problem here is that, in order to consume it you need to know how many are in the collection. As Ed. S said in the comments, you may find it easier to work with CLI (if you can compile your C++ with /clr on). But if you can do that, then you can use .Net types in C++ (such as List) and marshall your char*'s to Strings on the C++ side.

Otherwise, you can return the raw char*'s an handle it on the .Net side. To consume the char*'s in C# (and maybe having done C++, you will feel comfortable with this feature) you can use the unsafe keyword so you can convert those char*'s to System::String's in unsafe and add them to your .Net collections.

Upvotes: 1

Related Questions