定义外部“C” C# 中的函数

发布于 2024-09-29 14:46:47 字数 1927 浏览 0 评论 0原文

我有一个用 C# 编写的 ActiveX 控件,并且在 ActiveX 兼容程序 (CoDeSys) 中运行时可以工作。我遇到的问题是,为了让 CoDeSys 与 ActiveX 控件交互,CoDeSys 需要 dll 导出函数原型:

void ExecuteActiveXCall(IUnknown* pUnk, char* pszId, char* pszParam, char* pszReturnBuffer, int nReturnBufferSize, DWORD* pdwReturnFlag);

我已经研究过如何像在 C++ 中那样导出它,但没有成功,如图所示在此示例中:

extern "C" __declspec (dllexport) void ExecuteActiveXCall(IUnknown* pUnk, char* pszId, char* pszParam, char* pszReturnBuffer, int nReturnBufferSize, DWORD* pdwReturnFlag)
{
  if (strcmp(pszId, "IWebBrowser|GoBack") == 0)  
  {
    IUnknown* pNewUnk;
    IWebBrowser* pwb;
    pUnk->QueryInterface(IID_IWebBrowser, (void**) &pNewUnk);
    pwb = (IWebBrowser*) pNewUnk;

    if (pwb)
    {
      pwb->GoBack();
      pwb->Release();
    }
  }
  else if (strcmp(pszId, "IWebBrowser|GoForward") == 0)
  {
    IUnknown* pNewUnk;
    IWebBrowser* pwb;
    pUnk->QueryInterface(IID_IWebBrowser, (void**) &pNewUnk);
    pwb = (IWebBrowser*) pNewUnk;

    if (pwb)
    {
      pwb->GoForward();
      pwb->Release();
    }
  }
}

C# 确实有一个 extern 关键字,但它不允许您提供函数定义(至少我还没有找到方法)。尝试此操作后:

extern unsafe void ExecuteActiveXCall(
        [MarshalAs(UnmanagedType.IUnknown)] object pUnk, 
        char* pszId, 
        char* pszParam,
        char* pszReturnBuffer, 
        int nReturnBufferSize,
        UInt32* pdwReturnFlag)
    {

    }

出现以下错误:

'AlarmsCSharp.AlarmsControl.ExecuteActiveXCall(object, char*, char*, char*, int, uint*)' cannot be extern and declare a body

是否有人尝试在 C# dll 中导出函数?

有什么解决方法吗? (我想到了 [DllImport("AlarmsCSharp.dll")] 并在 C++ dll 中调用 C#,但我想我会看看以前是否有人有解决方案)

也许我想多了并且不需要导出此函数,因为 ActiveX 控件已经能够与 C# 代码进行交互。

编辑:我对从 C++ 函数原型到 C# 接口声明的翻译有一种感觉。如果对 C++/C# 编程有更多经验的人可以验证我的翻译是否正确,这可能会有所帮助。

I have an ActiveX control written in C# and working when run in an ActiveX compatible program (CoDeSys). The problem I've come across is that in order to allow CoDeSys to interact with the ActiveX control, CoDeSys requires the dll to export the function prototype:

void ExecuteActiveXCall(IUnknown* pUnk, char* pszId, char* pszParam, char* pszReturnBuffer, int nReturnBufferSize, DWORD* pdwReturnFlag);

I've looked without success on how to export this like you can in C++, as shown in this example:

extern "C" __declspec (dllexport) void ExecuteActiveXCall(IUnknown* pUnk, char* pszId, char* pszParam, char* pszReturnBuffer, int nReturnBufferSize, DWORD* pdwReturnFlag)
{
  if (strcmp(pszId, "IWebBrowser|GoBack") == 0)  
  {
    IUnknown* pNewUnk;
    IWebBrowser* pwb;
    pUnk->QueryInterface(IID_IWebBrowser, (void**) &pNewUnk);
    pwb = (IWebBrowser*) pNewUnk;

    if (pwb)
    {
      pwb->GoBack();
      pwb->Release();
    }
  }
  else if (strcmp(pszId, "IWebBrowser|GoForward") == 0)
  {
    IUnknown* pNewUnk;
    IWebBrowser* pwb;
    pUnk->QueryInterface(IID_IWebBrowser, (void**) &pNewUnk);
    pwb = (IWebBrowser*) pNewUnk;

    if (pwb)
    {
      pwb->GoForward();
      pwb->Release();
    }
  }
}

C# does have an extern keyword, but it doesn't allow you to provide the function definition (at least I haven't found a way). After attempting this:

extern unsafe void ExecuteActiveXCall(
        [MarshalAs(UnmanagedType.IUnknown)] object pUnk, 
        char* pszId, 
        char* pszParam,
        char* pszReturnBuffer, 
        int nReturnBufferSize,
        UInt32* pdwReturnFlag)
    {

    }

The following error occurs:

'AlarmsCSharp.AlarmsControl.ExecuteActiveXCall(object, char*, char*, char*, int, uint*)' cannot be extern and declare a body

Has anyone attempted exporting a function in a C# dll?

Are there any workarounds? (I had the thought of [DllImport("AlarmsCSharp.dll")] and calling C# in the C++ dll, but figured I'd see if anyone had a solution before)

Perhaps I'm over thinking this and don't need to export this function since the ActiveX control is able to interact already with the C# code.

EDIT: I have a feeling my translation from the C++ function prototype to the C# interface declaration. If someone with more experience with C++/C# programming could verify that I did that translation correct or incorrect, it may be of some help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橙幽之幻 2024-10-06 14:46:47

你说CoDeSys是ActiveX兼容的;您尝试过使用 COM 互操作吗?

You say that CoDeSys is ActiveX-compatible; have you tried using COM interop?

雄赳赳气昂昂 2024-10-06 14:46:47

似乎有3个主要选项;第一个是设置 COM 互操作,您可以在其中使用 COM 实例化 C# 控件/类。我确信如果您进行一些搜索,您可以找到更多相关信息。

第二个选项是使您的 C++ 模块混合托管/非托管,如下所述:
http://social. msdn.microsoft.com/Forums/en-US/vclanguage/thread/5345a27a-a614-4a74-9f6d-ea7a999ddf83/

第三个选项是使用“反向 PInvoke”,如下所述:http://tigerang.blogspot.com/2008/09/reverse-pinvoke.html

可能有是其他选择;这些是我所知道的。

There seems to be 3 main options; the first is to set up COM interop where you can instantiate your C# control / class using COM. I'm sure if you do some searching you can find some more info on that.

The second option is to make your c++ module mixed managed/unmanaged, as described here:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/5345a27a-a614-4a74-9f6d-ea7a999ddf83/

The third option is to use "reverse PInvoke" as described here: http://tigerang.blogspot.com/2008/09/reverse-pinvoke.html

There may be other options; those are the ones I know of.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文