none
在C#调用C的dll,报“未找到入口”;什么情况? RRS feed

  • 问题

  • 环境VS2010+Nsight2

    kernel.cu 相当于C,编译成TestDll.DLL

    #include "cuda_runtime.h"
    #include "device_launch_parameters.h"
    
    #include <stdio.h>
    
    cudaError_t addWithCuda(int *c, const int *a, const int *b, size_t size);
    
    __global__ void addKernel(int *c, const int *a, const int *b)
    {
      int i = threadIdx.x;
      c[i] = a[i] + b[i];
    }
    
    int __declspec(dllexport) cu_main(int a[],int b[])
    {
     const int arraySize = 5;
      int c[arraySize] = { 0 };
    
      // Add vectors in parallel.
      cudaError_t cudaStatus = addWithCuda(c, a, b, arraySize);
      if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addWithCuda failed!");
        return 1;
      }
    
      printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
        c[0], c[1], c[2], c[3], c[4]);
    
     // cudaDeviceReset must be called before exiting in order for profiling and
     // tracing tools such as Parallel Nsight and Visual Profiler to show complete traces.
      cudaStatus = cudaDeviceReset();
      if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceReset failed!");
        return 1;
      }
    
      return 0;
    }
    
    

    Program.cs:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace ConsoleTest
    {
      class Program
      {
        [DllImport (".\\Cuda\\TestDll.dll",CharSet=CharSet.Auto)]
        public static extern int cu_main(int[] arg1, int[] arg2);
    
        static void Main(string[] args)
        {
          int[] a = { 1, 2, 3, 4, 5 };
          int[] b = { 10, 20, 30, 40, 50 };
          cu_main(a, b);
    
          Console.ReadLine();
          // end static void Main(string[] args)
        }
        // end class Program
      }
      // end namespace ConsoleTest
    }
    
    
    

    文件列表:

    D:\MyProject\CUDA\TestDll\Bin>dir /s
     驱动器 D 中的卷是 Studio
     卷的序列号是 1059-D0BD

     D:\MyProject\CUDA\TestDll\Bin 的目录

    2011/06/12  08:50    <DIR>          .
    2011/06/12  08:50    <DIR>          ..
    2011/06/12  08:50             5,120 ConsoleTest.exe
    2011/06/12  08:50            11,776 ConsoleTest.pdb
    2011/06/12  08:44            11,600 ConsoleTest.vshost.exe
    2010/03/17  22:39               490 ConsoleTest.vshost.exe.manifest
    2011/06/12  08:50    <DIR>          Cuda
                   4 个文件         28,986 字节

     D:\MyProject\CUDA\TestDll\Bin\Cuda 的目录

    2011/06/12  08:50    <DIR>          .
    2011/06/12  08:50    <DIR>          ..
    2011/03/23  07:04           407,656 cudart32_40_12.dll
    2011/03/23  07:04           576,616 cudart64_40_12.dll
    2011/06/12  08:50            75,776 TestDll.dll
    2011/06/12  08:50               643 TestDll.exp
    2011/06/12  08:50           356,412 TestDll.ilk
    2011/06/12  08:50             1,748 TestDll.lib
    2011/06/12  08:50           388,096 TestDll.pdb
                   7 个文件      1,806,947 字节

         所列文件总数:
                  11 个文件      1,835,933 字节
                   5 个目录 10,565,853,184 可用字节

    报错信息。

    D:\MyProject\CUDA\TestDll\Bin>ConsoleTest.exe

    未经处理的异常:  System.EntryPointNotFoundException: 无法在 DLL“.\Cuda\TestDll.
    dll”中找到名为“cu_main”的入口点。
       在 ConsoleTest.Program.cu_main(Int32[] arg1, Int32[] arg2)
       在 ConsoleTest.Program.Main(String[] args) 位置 D:\MyProject\CUDA\TestDll\Con
    soleTest\Program.cs:行号 18

    求助大侠,谢谢。

     

    2011年6月12日 1:13

答案

  • 你好,

    1. 建议你先在函数名的修饰符前加extern "C" 作为修饰符:

    extern "C" int __declspec(dllexport) cu_main(int a[],int b[])
    此方法不可行,我们再通过加入.def文件的方法。

    2. 加入.def方法,此文件需要手动加入项目,再重新编译dll。

    def文件中,library 后面是dll的名字,在你的code中看来,应该是TestDLL, exports 后面是需要导出的函数名。


    如果您对我们的论坛在线支持服务有任何的意见或建议,请通过邮件告诉我们。
    MSDN 论坛好帮手 立刻免费下载  MSDN 论坛好帮手
    • 已建议为答案 Paul Zhou 2011年6月16日 8:14
    • 已标记为答案 Paul Zhou 2011年6月21日 7:59
    2011年6月16日 5:26

全部回复

  • 你好,

    请尝试修改DllImport的入口元素:

    [DllImport (".\\Cuda\\TestDll.dll",CharSet=CharSet.Auto,EntryPoint = "cu_main")]


    如果您对我们的论坛在线支持服务有任何的意见或建议,请通过邮件告诉我们。
    MSDN 论坛好帮手 立刻免费下载  MSDN 论坛好帮手
    2011年6月13日 9:28
  • 你好,

    请尝试修改DllImport的入口元素:

    [DllImport (".\\Cuda\\TestDll.dll",CharSet=CharSet.Auto,EntryPoint = "cu_main")]


    如果您对我们的论坛在线支持服务有任何的意见或建议,请通过邮件告诉我们。
    MSDN 论坛好帮手 立刻免费下载  MSDN 论坛好帮手

    改了:[DllImport(".\\Cuda\\TestDll.dll", CharSet = CharSet.Auto, EntryPoint = "cu_main")]

    但问题依旧。

    2011年6月13日 13:22
  • 你好,

    看起来你的DLL是基于C++而不是C语言的。

    实际上C++和C语言的编译器在生成DLL的时候,函数名并不是和我们代码中写的函数名一致的,编译器会给函数名加一串前缀字符。为了导出到Managed code中作为导出函数名,而不添加其他字符,在C++和C中是不一样的。

    如果是在C++中, 我们在导出方法声明中加入extern “C”,这样,就可以作为导出方法名使用了。

    如果是在C中,我们在编译DLL前,要加入.c程序的.Def,声明函数库,再编译导出函数,具体做法参照:

    http://support.microsoft.com/kb/106553


    如果您对我们的论坛在线支持服务有任何的意见或建议,请通过邮件告诉我们。
    MSDN 论坛好帮手 立刻免费下载  MSDN 论坛好帮手
    2011年6月15日 8:55
  • 你好,

    看起来你的DLL是基于C++而不是C语言的。

    实际上C++和C语言的编译器在生成DLL的时候,函数名并不是和我们代码中写的函数名一致的,编译器会给函数名加一串前缀字符。为了导出到Managed code中作为导出函数名,而不添加其他字符,在C++和C中是不一样的。

    如果是在C++中, 我们在导出方法声明中加入extern “C”,这样,就可以作为导出方法名使用了。

    如果是在C中,我们在编译DLL前,要加入.c程序的.Def,声明函数库,再编译导出函数,具体做法参照:

    http://support.microsoft.com/kb/106553


    你提供的链接我去看看,先谢了。
    2011年6月15日 13:11
  • 但.def文件怎么写?有教程吗?
    2011年6月15日 13:31
  • 我在网上照改了一段.def: LIBRARY cu_TestMain EXPORTS cu_main @1 编译了一下能用了,但不知道这些命令是什么意思。虽然结果是正常打印了,但调试的时候出了一个提示: “检测到PInvokeStackImbalance 对 PInvoke 函数“ConsoleTest!ConsoleTest.Program::cu_main”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。" 貌似得明天再研究了。
    2011年6月15日 13:40
  • Hi, 
    有另一種方法,直接將 TestDll.dll 放入
    D:\MyProject\CUDA\TestDll\Bin\Debug\ 試試。

    2011年6月16日 4:30
  • Hi, 
    有另一種方法,直接將 TestDll.dll 放入
    D:\MyProject\CUDA\TestDll\Bin\Debug\ 試試。

    这种方法不管用。Cuda论坛提供的也只有.def这一种方法。

    2011年6月16日 5:11
  • 另,留2个收藏链接:

    1) 使用 DEF 文件从 DLL 导出
        http://msdn.microsoft.com/zh-cn/library/d91k01sh%28v=vs.80%29.aspx
    2) 模块定义 (.def) 文件
        http://msdn.microsoft.com/zh-cn/library/28d6s79h%28v=vs.80%29.aspx

    2011年6月16日 5:13
  • 你好,

    1. 建议你先在函数名的修饰符前加extern "C" 作为修饰符:

    extern "C" int __declspec(dllexport) cu_main(int a[],int b[])
    此方法不可行,我们再通过加入.def文件的方法。

    2. 加入.def方法,此文件需要手动加入项目,再重新编译dll。

    def文件中,library 后面是dll的名字,在你的code中看来,应该是TestDLL, exports 后面是需要导出的函数名。


    如果您对我们的论坛在线支持服务有任何的意见或建议,请通过邮件告诉我们。
    MSDN 论坛好帮手 立刻免费下载  MSDN 论坛好帮手
    • 已建议为答案 Paul Zhou 2011年6月16日 8:14
    • 已标记为答案 Paul Zhou 2011年6月21日 7:59
    2011年6月16日 5:26