如何从非托管代码调用托管代码?

发布于 2024-07-08 09:47:43 字数 134 浏览 7 评论 0原文

我想从非托管 C++ 调用我的 .NET 代码。 我的进程入口点是基于 .NET 的,因此我不必担心托管 CLR。 我知道可以使用 .NET 对象的 COM 包装器来完成此操作,但我想访问托管类的各个静态方法,因此 COM 不是我最短/最简单的途径。

I want to call my .NET code from unmanaged C++. My process entrypoint is .NET based, so I don't have to worry about hosting the CLR. I know it can be done using COM wrappers for .NET objects, but I would like to access individual static methods of managed classes, so COM isn't my shortest/easiest route.

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

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

发布评论

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

评论(6

泪是无色的血 2024-07-15 09:47:43

看看这个解决方案:
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagementexports
该解决方案允许通过使用 [DllExport] 属性(与 P/Invoke DllImport 相反)装饰函数来从 C 调用 C# 函数。

示例:

C# 代码

class Test
{
     [DllExport("add", CallingConvention = CallingConvention.StdCall)]
     public static int Add(int left, int right)
     {
         return left + right;
     } 
}

C 代码:

 extern "C" int add(int, int);

 int main()
 {
      int z = add(5,10);
      printf("The solution is found!!! Z is %i",z);
      return 0;
 }

输出:

The solution is found!!! Z is 15

更新:评论中有一个问题和一个很好的答案:

如何在非托管项目中包含 dll?

您必须链接到编译 C# 代码时生成的 .lib 文件 (https://msdn.microsoft.com/en-us/library/ba1z7822.aspx?f=255&MSPPError=-2147217396)

Look at this solution:
https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports
The solution allows to call C# function from C by decorating your function with [DllExport] attribute (opposite of P/Invoke DllImport).

Exmaple:

C# code

class Test
{
     [DllExport("add", CallingConvention = CallingConvention.StdCall)]
     public static int Add(int left, int right)
     {
         return left + right;
     } 
}

C code:

 extern "C" int add(int, int);

 int main()
 {
      int z = add(5,10);
      printf("The solution is found!!! Z is %i",z);
      return 0;
 }

Output:

The solution is found!!! Z is 15

Update: There is a question and a good answer in comments:

How do I include the dll in the unmanaged project?

You have to link to the .lib file that is generated upon compiling your C# code (https://msdn.microsoft.com/en-us/library/ba1z7822.aspx?f=255&MSPPError=-2147217396)

征﹌骨岁月お 2024-07-15 09:47:43

假设您正在谈论真正的非托管代码 - 不仅仅是在使用 /clr 编译的混合模式程序集中运行的本机 C++ - 最简单的方法是在 C++/CLI 中创建 .NET 代码的包装器。 然后,您可以通过使用 __declspec(dllexport) 标记 C++/CLI 方法来导出它们。

或者,如果您可以控制非托管代码的调用,则可以将函数指针编组到 .NET 方法并将它们传递给非托管代码。

Assuming you are talking about real unmanaged code - not just native C++ running in a mixed-mode assembly compiled with /clr - the easiest way is to create a wrapper to your .NET code in C++/CLI. You can then export the C++/CLI methods by just marking them with __declspec(dllexport).

Alternatively, if you have control over the invocation of the unmanaged code, you can marshal function-pointers to your .NET methods and pass them to the unmanaged code.

我早已燃尽 2024-07-15 09:47:43

查看 GCHandle 类和gcroot 关键字,它为 GCHandle 提供类型安全的模板化包装器。

您可以使用它们来保存对本机代码中的 CLR 对象(或装箱值)的引用。

MSDN 有一个基本教程此处

Take a look at the GCHandle class and the gcroot keyword, which provides a typesafe, templated wrapper around GCHandle.

You can use these to hold a reference to a CLR object (or a boxed value) in native code.

MSDN has a basic tutorial here.

阿楠 2024-07-15 09:47:43

我相信您正在寻找 Reverse PInvoke。 如果你用谷歌搜索反向 pinvoke,你会得到很多有用的条目。 我认为下面有一个很好的快速但肮脏的例子。

PInvoke-反向 PInvoke和 __stdcall - __cdecl

I believe you are looking for Reverse PInvoke. If you google for reverse pinvoke you'll get a lot of helpful entries. I think the following has a good quick and dirty example.

PInvoke-Reverse PInvoke and __stdcall - __cdecl

陈年往事 2024-07-15 09:47:43

您的调用代码是启用了 /clr 的 C++。 正确的?

如果是,那么您只需使用 using 语句即可在代码中使用 .NET dll。 像这样:

#using <Mydll.dll>

然后您可以简单地创建托管类的对象,例如:

MyNameSpace::MyClass^ obj = new MyNameSpace::MyClass();

如果您想让这个 obj 成为您的类的数据成员,那么使用 gcroot 是可行的方法。

Your calling code is C++ with /clr enabled. Right?

If yes, then you can simply use the using statement to use your .NET dll in your code. Something like:

#using <Mydll.dll>

and then you can simply make the objects of your managed classes like:

MyNameSpace::MyClass^ obj = new MyNameSpace::MyClass();

If you want to make this obj a data member of your class the using gcroot is the way to go.

蓝海 2024-07-15 09:47:43

在这里找到好方法 使用 C#在集成到不同的解决方案后,在 C++/CLI 的帮助下,本机 C++ 也发现了这些更改:

附加IncludeDirectories ...YahooAPIWrapper

附加依赖项 ...YahooAPIWrapper。 lib

以及与这两个项目的关系,能够在最后一个 DLL 中通过线程打开 C# 表单并从本机 C++ 发送信息,仅需要 ...APIWrapper.h 包含 - 应该做得更好,但可以工作;-)

public YahooAPI()
{
    new Thread(() =>
    {
        Thread.CurrentThread.IsBackground = true;
        ShowForm();
    }).Start();
}

private static Form1 form = null;
public static void ShowForm()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    form = new Form1();
    Application.Run(form);
}

public void SendValues(bool[] values)
{
    if (form != null && form.ready) ...
}

准备好是我的 bool 成员在表单初始化完成时设置的

Find nice way here Using C# from native C++ with the help of C++/CLI after integration to different solution found also these changes:

AdditionalIncludeDirectories ...YahooAPIWrapper

AdditionalDependencies ...YahooAPIWrapper.lib

And relations to both projects, was able to open C# form by thread in last DLL and send info from native C++, only ...APIWrapper.h include needed - should be done way better, but works ;-)

public YahooAPI()
{
    new Thread(() =>
    {
        Thread.CurrentThread.IsBackground = true;
        ShowForm();
    }).Start();
}

private static Form1 form = null;
public static void ShowForm()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    form = new Form1();
    Application.Run(form);
}

public void SendValues(bool[] values)
{
    if (form != null && form.ready) ...
}

ready is my bool member set when form initialization finished

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