经过实际验证的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,示例代码如下:
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(, 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进行编译,编译成功后会生成头文件,比如build\libpandoc.dll\libpandoc.dll-tmp\LibPandoc_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;
}
}
【参考资料】
Call a Haskell function in .NET
经过实际验证的C#调用Haskell的方法的更多相关文章
- 困扰多日的C#调用Haskell问题竟然是Windows的一个坑
最近一直被C#调用Haskell时的“尝试读取或写入受保护的内存”问题所困扰(详见C#调用haskell遭遇Attempted to read or write protected memory,C# ...
- C#调用haskell遭遇Attempted to read or write protected memory
1. Haskell的代码如下: 上面的代码中readMarkdown与writeHtmlString是pandoc中的函数,newString的作用是将String转换为IO CString. 2. ...
- js调用php和php调用js的方法举例
js调用php和php调用js的方法举例1 JS方式调用PHP文件并取得php中的值 举一个简单的例子来说明: 如在页面a.html中用下面这句调用: <script type="te ...
- Jquery Ajax调用aspx页面方法
Jquery Ajax调用aspx页面方法 在asp.net webform开发中,用jQuery ajax传值一般有几种玩法 1)普通玩法:通过一般处理程序ashx进行处理: 2)高级玩法:通过as ...
- zabbix调用api检索方法
环境 zabbix:172.16.128.16:zabbix_web:172.16.16.16/zabbix 用户名:Admin 密码:zabbix 获取的数据仅做参考,以Linux发送HTTP的PO ...
- ASP.Net:Javascript 通过PageMethods 调用后端WebMethod方法 + 多线程数据处理 示例
ASP.Net:Javascript 通过PageMethods 调用后端WebMethod方法 + 多线程数据处理 示例 2012年04月27日 16:59:16 奋斗的小壁虎 阅读数:4500 ...
- SNF快速开发平台MVC-EasyUI3.9之-WebApi和MVC-controller层接收的json字符串的取值方法和调用后台服务方法
最近项目组很多人问我,从前台页面传到后台controller控制层或者WebApi 时如何取值和运算操作. 今天就都大家一个在框架内一个取值技巧 前台JS调用代码: 1.下面是选中一行数据后右键点击时 ...
- Struts2 调用非execute方法
调用非execute方法 1)如果你的Action类是继承自ActionSupport的话,确切的说是重写了execute方法,ActionSupport里的默认实现就是返回"success ...
- Python开发基础-Day20继承实现原理、子类调用父类的方法、封装
继承实现原理 python中的类可以同时继承多个父类,继承的顺序有两种:深度优先和广度优先. 一般来讲,经典类在多继承的情况下会按照深度优先的方式查找,新式类会按照广度优先的方式查找 示例解析: 没有 ...
随机推荐
- 网卡驱动如何设置组播MAC地址
参考资料: https://blog.csdn.net/abccheng/article/details/50465268 将网卡加入到组播组中.
- Easyui form 表单中的 radio 无法一开始就选中原因
是因为你在form表单里面,所以会出现样式没有选中状态,必须要从后台去获取数据,然后再绑定.也就是初始化数据.
- New users can not log on Win8
方案: http://www.eightforums.com/tutorials/38838-user-profile-service-failed-sign-fix-windows-8-a.html ...
- 经典矩阵快速幂之一-----poj3233(矩阵套矩阵
题意:给你一个矩阵A,求S=A+A^2+A^3+...+A^k. 其实这个当时我看着毫无头绪,看了他们给的矩阵发现好!精!妙! 我们这样看 是不是有点思路! 没错!就是右上角,我们以此类推可以得到A+ ...
- oracle 中删除表 drop delete truncate
oracle 中删除表 drop delete truncate 相同点,使用drop delete truncate 都会删除表中的内容 drop table 表名 delete from 表名 ...
- Mysql #1406 Data too long 错误
Mysql #1406 Data too long 错误 http://blog.sina.com.cn/s/blog_68004f680100kgfh.html B. Mysql配置文件: “在 ...
- centos7 hive + 远程mysql 搭建笔记
1.require:java环境,本地可用的hadoop,远程可访问的mysql 2.拷贝hive文件(hive-2.2.1) 3.设置环境变量 export HIVE_HOME=/data/spar ...
- OEM-ODM-OBM
Original Equipment ManufacturerOriginal Design ManufacturerOwn Branding & Manufacturing OEM,即“原始 ...
- java json注解
(1)初级我们从几个简单的使用场景开始:重命名属性,忽略属性,以及修改属性所使用的类型.注意:下面的例子仅仅显示了成员属性(field properties),注解同样也可以用在成员方法(getter ...
- error C2065: 'IDD_DIALOG1' : undeclared identifier
添加资源文件 #include "resource.h"