-2

I am confused on how to reference my c code from my c# code. I have read around and realized that DLL's are useful, but I do not understand how to connect my dll. From my understanding I make the dll from my c code? Please help

C# (visual studio code)

public partial class Form1: Form{
  [DllImport("simple.dll", CallingConvention = CallingConvention.Cdec1)]
  public static extern void pinfo(string str);

  private void button1_Click(object sender, EventArgs e){
      pinfo("yay");
  }
}

C code - simple.c

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
__declspec( dllexport ) void pinfo(char* str){
    printf("You are in the method %s\n, str);
}

int main(void){
}

my question is how do I connect the c code to the c# code so that the line "You are in the method yay" prints out? I do not understand how to link a dll file to visual studio or how to create the dll file. thanks

J.Doe
  • 155
  • 1
  • 9
  • 3
    Check https://stackoverflow.com/questions/11425202/is-it-possible-to-call-a-c-function-from-c-net and https://stackoverflow.com/questions/2874603/is-it-possible-to-embed-c-code-in-a-c-sharp-project – javier_el_bene May 30 '17 at 20:30
  • Your code looks fine to me. What happens when you try to run it? (Note that you do need to export the `pinfo` function first). Use `__declspec( dllexport )` – Dai May 30 '17 at 20:32
  • @dai I added that line, I am unsure how to run it because I have a visual studio project and then a simple.c file that is not associated with my visual studio project, I am unsure how to link them – J.Doe May 30 '17 at 20:39
  • Read the documentation on how to create a dll. Did you do that? – David Heffernan May 30 '17 at 20:41

1 Answers1

0

There are 3 main steps for getting P/Invoke (DllImport) working in .NET:

  1. Export the function from the C/C++ project.

    In Visual C++, use the __declspec( dllexport ) and extern "C" modifiers to, respectively, tell the compiler to export the function in the DLL so it is visible by name, and to not mangle the name either - otherwise the compiler will remove the function entirely if it has no callers inside the project ("dead-code removal"). Functions can also be exported by an ordinal number instead, which presumably is not what you're interested in.

  2. Ensure you're building for the same ISA.

    When you use P/Invoke in .NET, the DLL you reference will be loaded into the hosting .NET process, so the DLL must be built to the same CPU instruction-set as the current .NET process. .NET projects run in AnyCPU mode by default, but in recent versions of Visual Studio they "prefer" 32-bit (x86) mode instead of 64-bit (x64 / AMD64). To prevent any confusion, decide if you want 32-bit or 64-bit mode and force your .NET project to build only for that ISA and then set your C/C++ project to build for that ISA too.

  3. Ensure the target DLL file is located in the PATH of the .NET executable - typically this means simply placing it in the same bin output directory as the built .NET executable.

    Note that as this DLL file is not a .NET assembly there is no concept of a "project reference" or "assembly reference", so you need to configure your project specifically so that Visual Studio (MSBuild) will copy the DLL file to your bin folder - you can do this by adding the DLL file to your .NET project root in Solution Explorer, then selecting the file and open the Properties window and choose "Build action: Content." and "Copy to output directory: Always".

Regarding "linking" - DLLs are not linked at compile-time - the clue is in the name: "dynamic-linking": the linking is performed at runtime by the operating system, not by the compiler.

For more information on P/Invoke, I recommend reading this QA: Why are Cdecl calls often mismatched in the "standard" P/Invoke Convention?

Community
  • 1
  • 1
Dai
  • 141,631
  • 28
  • 261
  • 374
  • Everything from "Note that your DllImport declaration is incorrect" is wrong. The unmanaged function is cdecl and the default marshaling is fine. – David Heffernan May 30 '17 at 21:51
  • No, you are wrong. Default marshaling is to null terminated character array using prevailing character set. Which defaults to ANSI on desktop windows. All documented. You should read the documentation. – David Heffernan May 30 '17 at 21:54
  • @DavidHeffernan My mistake. I did further reading and I misread the documentation. I've removed the incorrect assertions from my answer. – Dai May 30 '17 at 21:59