简体   繁体   中英

Callbacks from Managed C# to Unmanaged C++ Code

I am triggering my C# code and initiating a call to unmanaged C++ code. There is a callback in unmanaged code.

Below is my c# code where I am initializing my delegate.but unfortunately I am getting garbage value.and I am not able to understand whether it will work properly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ConnectToScriptEngineDll
{
    public class ConnectToScriptEngine
    {
        public unsafe delegate  float myCallBackPtr(float** tagValue1);
            
        
        [DllImport("LTscriptenginedll.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern unsafe int ConnectLiveData(myCallBackPtr ps, IntPtr* test, int** temp, bool bdiscconectConnection, bool bPyRequest);


        public unsafe float StartLiveInfo(string tagNameFromRequest)
        {
            string tagName = tagNameFromRequest;//"Motor_1.OutPut.VI";
            byte[] tagNameByte = Encoding.ASCII.GetBytes(tagName);
            IntPtr tagNamePtr = Marshal.UnsafeAddrOfPinnedArrayElement(tagNameByte, 0);

            IntPtr[] tagNameIntPtr = new IntPtr[2];
            tagNameIntPtr[0] = tagNamePtr;
            tagNameIntPtr[1] = IntPtr.Zero;

            int tagValueTemp = 0;
            int*[] tagValuePtr = new int*[2];
            tagValuePtr[0] = &tagValueTemp;
            tagValuePtr[1] = null;
            float test;

            fixed (int** tagValue1 = tagValuePtr)
            {
                fixed (IntPtr* tagName1 = tagNameIntPtr)
                {
                    try
                    {
                        myCallBackPtr obj = new myCallBackPtr(CallMethod);
                            
                        var finalTagValue = ConnectLiveData(obj, tagName1, tagValue1, false, true);
                        test = Convert.ToSingle(*tagValue1[0]);
                        return test;
                    }
                    catch (Exception ex)
                    {
                        return 0;
                    }
                }
            }
        }

        public unsafe static float CallMethod(float** tagValue1)
        {
            var test4 = Convert.ToSingle(*tagValue1[0]);
            Console.WriteLine("callbacked");
            return test4;
        }
    }
}

Below is the C++ method code

    USE_SE short ConnectLiveData(void* pCallBack, const char** pszTagNames, const int** pnTagAddress,
    bool bdiscconectConnection, bool bPyRequest)
{
    short lnResult = -1;
    Lstring lsErrorMsg;

    if (NULL == g_pLiveDataChannel)
    {
        g_pLiveDataChannel = new CLiveDataChannel("", g_bIncomingLogEnableFlag, g_bOutgoingLogEnableFlag);
        g_nLiveDataChannelsCount++;
    }

    CSLCallInfo* lpcSLCall = new CSLCallInfo(pszTagNames, pnTagAddress, (onDPConnectdata)pCallBack, bPyRequest);

    if (lpcSLCall->m_nTagCount > 100)
    {
        lsErrorMsg = "Invalid number of parameters received for StartLiveCall TagName = " + lpcSLCall->m_sTagNamesKey;
        ST_LOG_DATA_BASE(ERROR_MSG, APP_NAME, (char*)lsErrorMsg.c_str());
        delete lpcSLCall;
        lpcSLCall = NULL;
        return lnResult;
    }

    if (lpcSLCall->m_sTagNamesKey.empty())
    {
        lsErrorMsg = "Failed start StartLiveCall - fiiled to create CSLCallInfo key : TagName = " + lpcSLCall->m_sTagNamesKey;
        ST_LOG_DATA_BASE(ERROR_MSG, APP_NAME, (char*)lsErrorMsg.c_str());
        delete lpcSLCall;
        lpcSLCall = NULL;
        return lnResult;
    }

    lnResult = g_pLiveDataChannel->InitLiveDataCall(lpcSLCall, pszTagNames, pnTagAddress);

    if (lnResult >= 0)
    {
        g_mLiveDataChannelMutex.lock();
        g_LiveDataChannelsList.insert(std::pair<Lstring, Lpair<CLiveDataChannel*, Lstring>>
            (lpcSLCall->m_sTagNamesKey, Lpair<CLiveDataChannel*, Lstring>(g_pLiveDataChannel, "")));
        g_mLiveDataChannelMutex.unlock();
    }
    else
    {
        delete lpcSLCall;
        lpcSLCall = NULL;
    }

    return lnResult;
}

Managed function call should be marshaled. Try to replace:

var finalTagValue = ConnectLiveData(obj, tagName1, tagValue1, false, true);

with

var finalTagValue = ConnectLiveData(Marshal.GetFunctionPointerForDelegate(obj), tagName1, tagValue1, false, true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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