C # 调用 C 函数


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









posted @ 2010-07-28 12:00  b0b0  阅读(1479)  评论(1编辑  收藏  举报