• 经过实际验证的C#调用Haskell的方法


    【系统环境】

    Windows Server 2008 R2,Haskell Platform 2013.2.0.0,ghc 7.6.3,cabal 1.16.0

    【操作步骤】

    1. 安装Windows版Haskell Platform(不支持Windows Server 2012),Haskell Platform集成了cabal(相当于.NET中的msbuild+nuget), ghc(Glasgow Haskell Compiler,Haskell编译器)

    2. 编写Haskell代码保存于.hs文件中,代码中加上foreign export ccall,示例代码如下:

    Haskell代码

    3. 编写C代码保存于.c文件中,代码如下:

    #include <windows.h>
    #include <Rts.h>
    
    extern void __stginit_LibPandoc(void);
    
    BOOL STDCALL DllMain(HANDLE hModule, DWORD reason, void* reserved)
    {
      static char* args[] = {"libpandoc", NULL};
      if (reason == DLL_PROCESS_ATTACH) {
        startupHaskell(1, args, __stginit_LibPandoc);
      }
      return TRUE;
    }

    4. 编写cabal配置文件保存于.cabal文件中,比如:

    Name:                   libpandoc
    Version:                0.5
    Cabal-Version:          >= 1.2
    Build-Type:             Simple
    Executable libpandoc.dll
      If os(windows)
        CPP-Options:        -DWIN32
      Extensions:           ForeignFunctionInterface         
      Hs-Source-Dirs:       src
      Include-Dirs:         src
      C-Sources:            src/pandoc.c
      Install-Includes:     pandoc.h
      Main-Is:              LibPandoc.hs
      Ghc-Options:          -no-hs-main -optl-shared -optl-s 

    5. 在Haskell项目所在的文件夹运行命令cabal build进行编译,编译成功后会生成头文件,比如buildlibpandoc.dlllibpandoc.dll-tmpLibPandoc_stub.h

    #include "HsFFI.h"
    #ifdef __cplusplus
    extern "C" {
    #endif
    extern HsPtr markdownToHtml(HsPtr a1);
    #ifdef __cplusplus
    }
    #endif

    6. 创建用于调用Haskell的C#项目

    7. 将编译出来的dll文件(比如libpandoc.dll)复制到C#项目的bin文件夹中

    8. 在C#中通过DllImport引用Haskell编译出来的dll文件

    class Native
    {
        [DllImport("libpandoc", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        public static extern IntPtr markdownToHtml(byte[] markdown);
    }

    9. 在C#中调用Haskell通过foreign export ccall暴露出来的函数,示例代码如下:

    public class Processor 
    { 
        public string Process(string text)
        {
            var intPtr = Native.markdownToHtml(Encoding.UTF8.GetBytes(text));
            var html = Marshal.PtrToStringAnsi(intPtr);
            return html;
        } 
    }

     【参考资料】

    Calling Haskell from C#

    Call a Haskell function in .NET

    libpandoc源代码

    libpandoc-dotnet源代码

  • 相关阅读:
    php内存管理机制与垃圾回收机制
    PHP Laravel5实现的RBAC权限管理操作示例
    PHP实现微信企业付款到个人零钱步骤
    ThinkPHP 6.0 管道模式与中间件的实现分析
    深入讲解 Laravel 的 IoC 服务容器
    ThinkPHP6 核心分析:系统服务
    PHP 性能优化
    PHP 7.4 新语法:箭头函数
    深入理解 PHP 的 7 个预定义接口
    Java实现 LeetCode 795 区间子数组个数 (暴力分析)
  • 原文地址:https://www.cnblogs.com/dudu/p/csharp-call-haskell.html
Copyright © 2020-2023  润新知