繁体   English   中英

将结构数组从C#(。NET Core)传递到C ++(未使用)

[英]Passing Array of Structures from C#(.NET Core) to C++(unamnaged)

因此,我在线阅读了文档和无数示例,说明如何编排结构数组。 我已经整理了一些int数组,我已经整理了结构,但是现在我完全陷入了困境,无论我如何尝试都无法使其正常工作。 现在被卡住了一天以上。

结构/类,两者都尝试过

    [StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
public class SaveDetails
{
    [MarshalAs(UnmanagedType.LPWStr)]
    public string Log;
    public FILETIME FileTime;
    [MarshalAs(UnmanagedType.Bool)]
    public bool Saved;
}

Pinvoke和呼叫代表

public class LogSaveFiles : IDisposable
{
    [UnmanagedFunctionPointer(CallingConvention.Winapi,CharSet = CharSet.Unicode)]
    private delegate Status DLogSaveFiles([ In, Out] SaveDetails[] logsToSave, string destinationPath);
    private static DLogSaveFiles _dLogSaveFiles;

    private IntPtr PLogSaveFiles { get; set; }
    public bool LogSaveFilesAvailable => PLogSaveFiles != IntPtr.Zero;

    public LogSaveFiles(Importer importer)
    {
        if (importer.dllLibraryPtr!= IntPtr.Zero)
        {
            PLogSaveFiles = Importer.GetProcAddress(importer.dllLibrary, "LogSaveFiles");
        }
    }

    public Status SaveFiles(SaveDetails[] logsToSave,string destinationPath)
    {
        Status result = Status.FunctionNotAvailable;

        if (LogSaveFilesAvailable)
        {
            _dLogSaveFiles = (DLogSaveFiles)Marshal.GetDelegateForFunctionPointer(PLogSaveFiles, typeof(DLogSaveFiles));

            result = _dLogSaveFiles(logsToSave, destinationPath);
        }

        return result;
    }

    public void Dispose()
    {

    }
}

呼叫

      private void SaveLogs()
    {
        var logsToSave = new[]{
            new SaveDetails{
                FileTime = new FILETIME {dwHighDateTime = 3,dwLowDateTime = 5},
                Log = LogTypes.logDeviceLog,
                Saved = true},
            new SaveDetails{
                FileTime = new FILETIME {dwHighDateTime = 1,dwLowDateTime = 2},
                Log = LogTypes.logDeviceLog,
                Saved = false}
             };

        var pathToSave = "C:\\Logs";
        _logSaveFiles.SaveFiles(logsToSave, pathToSave);
    }

C ++公开调用

    typedef struct _LOG_SAVE_DETAILS
{
    LPTSTR      szLog;
    FILETIME    fromFileTime;
    BOOL        bSaved;
} LOG_SAVE_DETAILS, *PLOG_SAVE_DETAILS;


/* Function definitions */

ULY_STATUS _API LogSaveFiles (PLOG_SAVE_DETAILS   ppLogs [],
                                         LPCTSTR                szDestinationPath);

到目的地的路径已正确传递,但是结构数组从未尝试通过,因此在尝试访问它时会导致访问冲突。 起初,我认为LPTSTR的处理不正确是一个问题,但我自己实施了其他调用,并成功地将其编组。

我已经阅读了https://docs.microsoft.com/zh-cn/dotnet/framework/interop/marshaling-data-with-platform-invoke上的所有内容,都表明我的方法是正确的,但事实并非如此工作。

任何帮助表示赞赏。

简单的解决方案:C侧将PLOG_SAVE_DETAILS ppLogs []更改为LOG_SAVE_DETAILS ppLogs [] ,然后C#侧将public class SaveDetails更改为public struct SaveDetails

整理对象数组似乎很困难(我无法做到)。 编组结构体的工作原理。 另一种方法是手动进行封送处理,但这很麻烦。

手动封送处理的“痛苦”(仅修改的代码行):

[UnmanagedFunctionPointer(CallingConvention.Winapi, CharSet = CharSet.Unicode)]
private delegate Status DLogSaveFiles(IntPtr[] logsToSave, string destinationPath);

接着

public Status SaveFiles(SaveDetails[] logsToSave, string destinationPath)
{
    Status result = Status.FunctionNotAvailable;

    if (LogSaveFilesAvailable)
    {
        if (_dLogSaveFiles == null)
        {
            _dLogSaveFiles = (DLogSaveFiles)Marshal.GetDelegateForFunctionPointer(PLogSaveFiles, typeof(DLogSaveFiles));
        }

        int size = Marshal.SizeOf(typeof(SaveDetails));

        IntPtr basePtr = IntPtr.Zero;
        IntPtr[] ptrs = new IntPtr[logsToSave.Length + 1];

        try
        {
            basePtr = Marshal.AllocHGlobal(size * logsToSave.Length);

            for (int i = 0; i < logsToSave.Length; i++)
            {
                ptrs[i] = IntPtr.Add(basePtr, (i * size));
                Marshal.StructureToPtr(logsToSave[i], ptrs[i], false);
            }

            result = _dLogSaveFiles(ptrs, destinationPath);
        }
        finally
        {
            if (basePtr != IntPtr.Zero)
            {
                for (int i = 0; i < logsToSave.Length; i++)
                {
                    if (ptrs[i] != IntPtr.Zero)
                    {
                        Marshal.DestroyStructure(ptrs[i], typeof(SaveDetails));
                    }
                }

                Marshal.FreeHGlobal(basePtr);
            }
        }
    }

    return result;
}

重要说明:这是封送处理程序C#-> C ++。 C ++不得以任何方式修改接收到的数组,否则会发生内存泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM