第一步,我先从简单的调用出发,定义了一个简单的函数,该函数仅仅实现一个整数加法求和:
LIBEXPORT_API int mySum(int a,int b){ return a+b;}
C# 导入定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern int mySum (int a,int b);
}
在C#中调用测试:
int iSum = RefComm.mySum(,);
运行查看结果iSum为5,调用正确。第一步试验完成,说明在C#中能够调用自定义的动态链接库函数。
第二步,我定义了字符串操作的函数(简单起见,还是采用前面的函数名),返回结果为字符串:
LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a); return a;}
C# 导入定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, string b);
}
在C#中调用测试:
string strDest="";
string strTmp= RefComm.mySum("45", strDest);
运行查看结果 strTmp 为"45",但是strDest为空。我修改动态链接库实现,返回结果为串b:
LIBEXPORT_API char *mySum(char *a,char *b){sprintf(b,"%s",a) return b;}
修改 C# 导入定义,将串b修改为ref方式:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
在C#中再调用测试:
string strDest="";
string strTmp= RefComm.mySum("45", ref strDest);
运行查看结果 strTmp 和 strDest 均不对,含不可见字符。再修改 C# 导入定义,将CharSet从Auto修改为Ansi:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, string b);
}
在C#中再调用测试:
string strDest="";
string strTmp= RefComm. mySum("45", ref strDest);
运行查看结果 strTmp 为"45",但是串 strDest 没有赋值。第二步实现函数返回串,但是在函数出口参数中没能进行输出。再次修改 C# 导入定义,将串b修改为引用(ref):
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
运行时调用失败,不能继续执行。
第三步,修改动态链接库实现,将b修改为双重指针:
LIBEXPORT_API char *mySum(char *a,char **b){sprintf((*b),"%s",a); return *b;}
C#导入定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern string mySum (string a, ref string b);
}
在C#中调用测试:
string strDest="";
string strTmp= RefComm. mySum("45", ref strDest);
运行查看结果 strTmp 和 strDest 均为"45",调用正确。第三步实现了函数出口参数正确输出结果。
第四步,修改动态链接库实现,实现整数参数的输出:
LIBEXPORT_API int mySum(int a,int b,int *c){ *c=a+b; return *c;}
C#导入的定义:
public class RefComm
{
[DllImport("LibEncrypt.dll",
EntryPoint=" mySum ",
CharSet=CharSet.Ansi,CallingConvention=CallingConvention.StdCall)]
public static extern int mySum (int a, int b,ref int c);
}
在C#中调用测试:
int c=0;
int iSum= RefComm. mySum(,, ref c);
运行查看结果iSum 和c均为5,调用正确。
经过以上几个步骤的试验,基本掌握了如何定义动态库函数以及如何在 C# 定义导入,有此基础,很快我实现了变长加密函数在 C# 中的调用,至此目标实现。
三、结论
在 C# 中调用 C++ 编写的动态链接库函数,如果需要出口参数输出,则需要使用指针,对于字符串,则需要使用双重指针,对于 C# 的导入定义,则需要使用引用(ref)定义。
对于函数返回值,C# 导入定义和 C++ 动态库函数声明定义需要保持一致,否则会出现函数调用失败。定义导入时,一定注意 CharSet 和 CallingConvention 参数,否则导致调用失败或结果异常。运行时,动态链接库放在 C# 程序的目录下即可,我这里是一个 C# 的动态链接库,两个动态链接库就在同一个目录下运行。
每年六月的第三个星期天,今年是6月19号。很久以前人们就开始歌颂母爱的伟大,而忽略了父亲。在一个家庭中父亲也承担了很大的责任。他们也需要我们的关心和关爱。送礼物可以选择送酒,买酒上尚饮网。
父亲节:6月的第三个星期日为父亲节(2010年父亲节是6月20日,星期日)。
送我爸一个电动剃须刀,皮带,打火机等等。
父亲节送石斛兰,这是父亲之花。
爸爸,你在我心里最最伟大!
爸爸的教诲像一盏灯,为我照亮前程;爸爸的关怀像一把伞,为我遮蔽风雨。祝您父亲节快乐!!
父亲节在每年6月份的第三个星期日,今年的父亲节是6月21日。 选6月过父亲节是因为这时的阳光是一年之中最晴朗的,象征父亲给子女火热而充满活力的爱。 你是否已经想好一种方式来表达你对父亲的感情。一束美丽的鲜花,或者一次贴心的陪伴,都可以成为这份礼物的载体。也许当你献上礼物时,父亲只是微微一笑或是淡然一语,但是我们都知道,他的心此刻正在感动。 创意一:送束鲜花,做顿早餐 ; 创意二:给老爸寄一张明信片; 创意三:送老爸一次体检; 创意四:笔记本、领带、香水; 创意五:陪老爸买衣服,享受天伦; 创意六:带老爸去旅游; 创意七:写一篇《我的父亲》; 创意八:发一条祝福短信给老爸。
今年的父亲节是在6月15号哦! 通常以送黄色的玫瑰花为主。在有的国家,把黄色视为男性的颜色。在日本,父亲节时必须送白色的玫瑰花
今天是父亲节,跟您自己的父亲道声:节日快乐吧!我祝您的父亲健康长寿,笑口常开!同时祝愿天下所有的父亲节日快乐!