c 代码:
#include <stdio.h>
#include <assert.h>
#define MAXLEN 1000
int getline(char[] ,int);
//供C# 调用 __declspec
__declspec(dllexport) void reverseline(char dest[],const char source[]);
int main(int argc, char *argv[])
{
char currentline[MAXLEN];
int maxcount=0;
int currentlen=0;
char resultline[MAXLEN];
while(currentlen=getline(currentline,MAXLEN))
{
reverseline(resultline,currentline);
printf("\n %s \n",resultline);
}
return 0;
}
int getline(char line[],int len)
{
//printf("-------start getline-----------------------\n");
char c;
int i=0;
for(;(i<len&&(c=getchar())!=EOF &&(c!='\n'));i++)
{
line[i]=c;
//printf(" line[%d]=%c",i,c);
}
line[i]='\0';
//printf("\n line[%d]=null \n",i+1);
//printf("-------end getline-----------------------\n");
return i;
}
void reverseline(char dest[],const char source[])
{
int i=0;
int len=0;
for(i=0;i<MAXLEN;i++)
{
if(source[i]=='\0')
{
len=i;
break;
}
//dest[i]=source[i];
}
//printf("\nlen =%d \n",len);
for(i=0;i<len;i++)
{
dest[len-1-i]=source[i];
//printf(" dest[%d]=%c",len-1-i,dest[len-1-i]);
}
dest[len]='\0';
}
使用 ms cl.exe ,生成 dll
cl.exe reverseline.c /LD
注意是/LD 是大写,如果写成 /ld,直接被cl 忽略
正常情况写的编译输出:
reverseline.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:reverseline.dll
/dll
/implib:reverseline.lib
reverseline.obj
正在创建库 reverseline.lib 和对象 reverseline.exp
导出函数不加__declspec(dllexport) 编译输出:
reverseline.c
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:reverseline.dll
/dll
/implib:reverseline.lib
reverseline.obj
C# 代码:把 reverseline.dll 拷到 C# 生成的 .exe的目录
C# 代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace CallCLib
{
class CLib
{
[DllImport("reverseline.dll")]
public static extern void reverseline(StringBuilder dest, StringBuilder surce);
}
class Program
{
static void Main(string[] args)
{
//char[] a = { '1','2','3'};
//char[] b=new char[]{};
StringBuilder a = new StringBuilder ("123");
StringBuilder b =new StringBuilder ();
CLib.reverseline(b, a);
Console.WriteLine("a={0} b={1}",a,b);
Console.Read();
}
}
}
运行后生成的结果:
a=123 b=321
问题:
(1)如果按以下调用
public static extern void reverseline(char[] dest, char[] surce);
char[] a = { '1','2','3'};
char[] b=new char[]{};
CLib.reverseline(b, a);
异常:
未处理 System.AccessViolationException
Message="尝试读取或写入受保护的内存。这通常指示其他内存已损坏。"
Source="CallCLib"
StackTrace:
在 CallCLib.CLib.reverseline(Char[] dest, Char[] surce)
在 CallCLib.Program.Main(String[] args) 位置 E:\lhb\Program\CallCLib\CallCLib\Program.cs:行号 23
在 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()
InnerException:
(2)如果按以下调用
public static extern void reverseline(char[] dest, char[] surce);
string a = "123";
string b="";
CLib.reverseline(b, a);
运行后生成的结果:
a=123 b=
(2)如果在c 的导出函数不加__declspec(dllexport) ,直接是 void reverseline(char dest[],const char source[]) ;
异常:
未处理 System.EntryPointNotFoundException
Message="无法在 DLL“reverseline.dll”中找到名为“reverseline”的入口点。"
Source="CallCLib"
TypeName=""
StackTrace:
在 CallCLib.CLib.reverseline(Char[] dest, Char[] surce)
在 CallCLib.Program.Main(String[] args) 位置 E:\lhb\Program\CallCLib\CallCLib\Program.cs:行号 23
在 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()
InnerException:
问题:是不是 用c 标准库写的函数,不修改c 的源码(比如添加__declspec,或定义def 文件),就不能被.net调用?