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調用?