Функция обратного вызова C ++ для C# - PullRequest
0 голосов
/ 24 апреля 2020

Я хочу переписать функцию из C ++ в C#. У меня нет опыта работы с C ++, но это то, что я уже написал. Импорт DLL с некоторыми функциями уже работает. Но этот обратный вызов меня беспокоит. Пожалуйста, помогите мне:)

C ++ код:

/* Structure for PBORCA_CompileEntryImport callback function. */
typedef struct pborca_comperr  
{
    INT     iLevel;                         
    LPTSTR   lpszMessageNumber;             
    LPTSTR   lpszMessageText;               
    UINT    iColumnNumber;                  
    UINT    iLineNumber;                   

} PBORCA_COMPERR, FAR *PPBORCA_COMPERR;


/* Prototype for PBORCA_CompileEntryImport callback function.  */            
typedef PBCALLBACK(void, *PBORCA_ERRPROC) ( PPBORCA_COMPERR, LPVOID );

мой c# код:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct PBORCA_COMPERR
{
    public int iLevel;                            
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string lpszMessageNumber;               
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string lpszMessageText;                  
    public int iColumnNumber;                       
    public int iLineNumber;                        
}

private delegate void PBORCA_CALLBACK(IntPtr pDirEntry, IntPtr lpUserData);

1 Ответ

1 голос
/ 25 апреля 2020

Из того, что я понимаю, есть несколько возможных способов сделать это. Это будет зависеть от того, что вам нужно.

Вариант 1) Использование IntPtr и Marshal.GetFunctionPointerForDelegate

// A template of the function you want other code to call
// Your calling convention may be different
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] // note calling convention
delegate void PBORCA_CALLBACK(IntPtr pDirEntry, IntPtr lpUserData);  

class Orca
{
    [DllImport("LibraryName.dll")]
    private static extern int PBORCA_CompileEntryImport(
        IntPtr hORCASession,
        ...
        long lEntrySyntaxBuffSize,
        IntPtr pCompErrorProc, // note the IntPtr
        IntPtr pUserData);

    // An implementation of the function delegate (this will be called)
    private static void StaticImpOfTheCallback(IntPtr pDirEntry, IntPtr lpUserData)
    {
        // write code here (Notice: I'm a static function)
    }

    // An implementation of the function delegate (this will be called)
    private void NonStaticImpOfTheCallback(IntPtr pDirEntry, IntPtr lpUserData)
    {
        // write code here (Notice: I'm not static)
    }

    // Create a delegate object which will link the callback function
    private PBORCA_CALLBACK staticCallbackDel = StaticImpOfTheCallback; 

    public void SomeCallingFunction()
    {
        PBORCA_CompileEntryImport(
            0, 
            ... ,
            128, 
            Marshal.GetFunctionPointerForDelegate(staticCallbackDel), // Delegate to function ptr
            0);

        PBORCA_CompileEntryImport(
            0, 
            ... ,
            128, 
            Marshal.GetFunctionPointerForDelegate(
                new PBORCA_CALLBACK(NonStaticImpOfTheCallback) // create a delegate instance
            ), // Delegate to function ptr
            0);
    }
}

Вариант 2 Использование delegate непосредственно в определении

// A template of the function you want other code to call
// Your calling convention may be different
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] // note calling convention
delegate void PBORCA_CALLBACK(IntPtr pDirEntry, IntPtr lpUserData);  

class Orca
{
    [DllImport("LibraryName.dll")]
    private static extern int PBORCA_CompileEntryImport(
        IntPtr hORCASession,
        ...
        long lEntrySyntaxBuffSize,
        [MarshalAs(UnmanagedType.FunctionPtr)] // May or may not be needed
        PBORCA_CALLBACK pCompErrorProc, // note the use of the delegate
        IntPtr pUserData);

    // An implementation of the function delegate (this will be called)
    private static void StaticImpOfTheCallback(IntPtr pDirEntry, IntPtr lpUserData)
    {
        // write code here (Notice: I'm a static function)
    }

    // An implementation of the function delegate (this will be called)
    private static void NonStaticImpOfTheCallback(IntPtr pDirEntry, IntPtr lpUserData)
    {
        // write code here (Notice: I'm a static function)
    }

    // Create a delegate object which will link the callback function
    private PBORCA_CALLBACK staticCallbackDel = StaticImpOfTheCallback; 

    public void SomeCallingFunction()
    {
        PBORCA_CompileEntryImport(
            0, 
            ... ,
            128, 
            staticCallbackDel, // no need to convert the delegate
            0);

        PBORCA_CompileEntryImport(
            0, 
            ... ,
            128, 
            StaticImpOfTheCallback, // could call directly too.
            0);

        PBORCA_CompileEntryImport(
            0, 
            ... ,
            128, 
            NonStaticImpOfTheCallback, // could call directly too.
            0);

        // same as above (I think)
        PBORCA_CompileEntryImport(
            0, 
            ... ,
            128, 
            new PBORCA_CALLBACK(NonStaticImpOfTheCallback), // more explicit
            0);
    }
}

Это большинство из Варианты, которые я могу придумать. Один из них должен вам подойти. Если что-то выше неясно, я предлагаю вам прочитать некоторую документацию о том, как делегаты работают в обычном C#, и поэкспериментировать там, прежде чем пытаться использовать их в сочетании с кодом C ++. Для делегатов доступно множество учебных пособий, и один из них должен надеяться, что пенни упадут, если она этого еще не сделала.

Удачи

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...