从 C# 调用 C++ DLib 导致错误分配异常

Calling C++ DLib from C# results in bad allocation exception

如果我 运行 我的代码直接在 C++ 中 运行 就好了。但是,当我从 C# 调用它时,我收到一条错误的分配消息。我的 C++ 经验真的很低,但根据我阅读和修改的所有内容,我觉得这应该可行。

我的情况

通过面部识别传递图像路径,然后save/serialize结果到磁盘并return返回图像在数组中的索引(函数:int AddImageToCollection)

如果我 运行 我的代码与主要功能我得到完美的结果(图 1)但是如果我 运行 它通过 C# (图 2) 我得到以下信息:

我得到日志 4-1 而不是日志 4-2,e.what() 中的唯一错误是 "bad allocation"。我创建了一个无参数的测试函数,它被硬编码为 return 5 并且可以工作,因此它与这个更复杂的函数隔离开来,我相信它必须与将数据传递给 const char*.

图一

frontal_face_detector detector = get_frontal_face_detector();
shape_predictor sp;
anet_type net;

bool fileExists(const std::string& name) {
ifstream f(name.c_str());
return f.good();
}

void log(std::string name) {

}

int main(int argc, char** argv) try
{
string str = "C:\images\Me.jpg";
const char* c = str.c_str();

int whatIsMyIdx = AddImageToCollection(c);

cout << whatIsMyIdx << endl;

cin.get();
}
catch (std::exception& e)
{
    cout << e.what() << endl;
}

int AddImageToCollection(const char* imagePath)
{
    deserialize("shape_predictor_5_face_landmarks.dat") >> sp;
    deserialize("dlib_face_recognition_resnet_model_v1.dat") >> net;

    matrix<rgb_pixel> image;
    string imagePathStr(imagePath);

    load_image(image, imagePathStr);

    std::vector<matrix<rgb_pixel>> faces;

    if (fileExists("faces_in_collection.dat")) {
        deserialize("faces_in_collection.dat") >> faces;
    }

    auto facesDetected = detector(image);

    if (facesDetected.size() == 0) { return -1; }
    if (facesDetected.size() > 1) { return -2; }

    auto shape = sp(image, facesDetected[0]);

    log("4-1");

    matrix<rgb_pixel> face_chip;
    extract_image_chip(image, get_face_chip_details(shape, 150, 0.25), face_chip);

    log("4-2");

    faces.push_back(move(face_chip));
    serialize("faces_in_collection.dat") << faces;

    std::vector<matrix<float, 0, 1>> face_descriptors;

    if (fileExists("face_descriptors_in_collection.dat")) {
        deserialize("face_descriptors_in_collection.dat") >> face_descriptors;
    }

    face_descriptors.push_back(net(faces[faces.size() - 1]));

    serialize("face_descriptors_in_collection.dat") << face_descriptors;

    return faces.size() - 1; //Return Image's Index in Array
}

图2

    [DllImport("FacialRecognition.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int TestImageToCollection();

    [DllImport("FacialRecognition.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int AddImageToCollection([MarshalAs(UnmanagedType.LPStr)]string imagePath);

    private void Form1_Load(object sender, EventArgs e)
    {
        int whatIsMyTestIdx = TestImageToCollection();

        int whatIsMyIdx = AddImageToCollection(@"C:\images\Me.jpg");

        MessageBox.Show(whatIsMyIdx.ToString());
    }

您需要按以下方式调整您的代码

在 DLL 中

extern "C" __declspec(dllexport) int AddImageToCollection(LPCWSTR imagePath) { .... // you may need to convert from Unicode string to ANSI if you are calling function that accept ANSI strings }

并且在 c# 应用程序中

[DllImport("FacialRecognition.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] public static extern int AddImageToCollection(string imagePath);

并像

一样调用您的函数
int whatIsMyIdx = AddImageToCollection(@"C:\images\Me.jpg");

为使上述正常工作,请不要忘记将应用程序和 Dll 都编译为 Unicode。如果它们不同,您应该调整正确的进出口申报。