I'm trying to work with a C# DLL on Python. The code used to create to C# DLL is included with this question.
from ctypes import*
mydll = cdll.LoadLibrary("Z:\\9. Personal\\Jeet\\New
folder\\ClassLibrary1.dll")
mydll.Add(3,4)`
The code doesn't work and the error is:-
AttributeError: function 'Add' not found
Is there any alternative?
Iron Python is installed on the PC I'm using but I have never used it. Please give me a detailed answer with all steps.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary1
{
// Interface declaration.
public interface ICalculator
{
int Add(int Number1, int Number2);
};
public class Class1 : ICalculator
{
public int Add(int Number1, int Number2)
{
return Number1 + Number2;
}
}
}
Related
I have C# as my front end application and I want to call c++ dll from my c# but I am getting error.
I am posting my code here please help me out how to resolve this:
Program.cs
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestCSharp
{
class Program
{
[DllImport("C:\\Users\\xyz\\source\\repos\\Project1\\Debug\\TestCpp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void DisplayHelloFromDLL(StringBuilder name, int appId);
static void Main(string[] args)
{
try
{
StringBuilder str = new StringBuilder("name");
DisplayHelloFromDLL(str, str.Length);
str.Clear();
}
catch(DllNotFoundException exception)
{
Console.WriteLine(exception.Message);
}
catch(Exception exception)
{
Console.WriteLine("General exception " + exception.Message);
}
finally
{
Console.WriteLine("Try again");
}
}
}
}
and cpp code like below:
Header: source.h
#include <string>
using namespace std;
extern "C"
{
namespace Test
{
class test
{
public:
test();
__declspec(dllexport) void DisplayHelloFromDLL(char * name, int appId);
}
}
}
c++ class: source.cpp
#include <stdio.h>
#include "source.h"
Test::test::test()
{
printf("This is default constructor");
}
void Test::test::DisplayHelloFromDLL(char * name, int appId)
{
printf("Hello from DLL !\n");
printf("Name is %s\n", name);
printf("Length is %d \n", appId);
}
Code is building successfully but when I run this I got Unable to find an entry point named 'DisplayHelloFromDLL' in DLL.
Same CPP code when I am writing without using namespace and class, it is working fine.
i.e.
Header: source.h
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL(char * name, int appId);
}
c++ class: source.cpp
#include "source.h"
void DisplayHelloFromDLL(char * name, int appId)
{
printf("Hello from DLL !\n");
printf("Name is %s\n", name);
printf("Length is %d \n", appId);
}
So how do I use DLL which has namespaces and claases in my c# application.
Thanks for the answers.
I resolved the issue by making one extra class(Wrapper class) that contains the managed code. This wrapper class is called by the c# classes in the same way as I mentioned in the question. This wrapper class than call the c++ class and return the result to the UI.
The easiest way is to create a "proxy": set of clear-C functions, these will call your c++ functions.
I think calling c++ function is not good idea: name decoration is changed from version to version of compiler.
Do you have this project hosted somewhere?
On the first view I would say that you need to build the c++ project first (only the c++!!!) and then run the C# project.
Perhaps you would like to have a look here: Testprojects
Especially the "MessageBox" stuff shows how to use C++ with C#. There are some Testprojects with UWP as well.
I have this class library I created. And I am running into the issue of getting the library to work with a console application. This is just a basic assignment I'm working on but I do not know where I am going wrong. Here are my files:
Class Library:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test2
{
public class Test
{
public static string GetData(String prompt)
{
Console.WriteLine(prompt);
return Console.ReadLine();
}
public static int GetInt()
{
return Convert.ToInt32(GetData("Enter an interger"));
}
public static void put(String output)
{
Console.WriteLine(output);
}
public static void put(String output, String heading)
{
put(heading + '\n' + output);
}
public static void Main(String[] args)
{
int x = GetInt();
int y = GetInt();
if (x > 0 && y > 0) put(String.Format("Sum:{0}", x + y));
}
}
}
Console Application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Test2;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Test myTest = new Test();
Test.GetData(prompt);
}
}
}
My main issue I guess I have is calling the methods to run in the console application. No matter how much reading I do I can't seem to know what I am doing wrong.
You don't need a Main method in your class library. The Main method in your console application is the entry point to your application.
If the functionality in the Main method you've defined in your class library is what you're trying to achieve for the overall application then consider moving that functionality into the Main method in your console application.
You've made the methods in your class library static so you don't need to instantiate an object of type Test
So my solution for you would be to have this in your Main method of your console application:
int x = Test.GetInt();
int y = Test.GetInt();
if (x > 0 && y > 0) Test.put(String.Format("Sum:{0}", x + y));
Console.Read();
I would suggest reading up on Static Classes and Static Class members here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members
When deciding to make a Static class I always come back to this quote from the above link:
A static class can be used as a convenient container for sets of
methods that just operate on input parameters and do not have to get
or set any internal instance fields.
I would also consider changing the name of your Test class. Even in small test applications like this I find it is useful to use well defined names with meaning. It's good practice so that you will do it automatically in larger applications.
Finally, good luck with all your learning!
The C++ code is as follows
#include "stdafx.h"
#include <Windows.h>
#import "C:\shreyas\Documents\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.tlb" no_namespace
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
IMyClassPtr obj;
//iProgramPtr obj;
obj.CreateInstance(__uuidof(MyClass));
printf("value: %d",obj->display());
CoUninitialize();
getchar();
return 0;
}
The C# code is as follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace demo
{
[ComVisible(true)]
public interface IMyClass
{
int display();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
class MyClass : IMyClass
{
public int display()
{
Console.WriteLine("Hello");
return 10;
}
}
}
I would like to call the C# display function from C++ code. I have done the required settings in C# project properties. In the code obj.CreateInstance(__uuid(MyClass)); the MyClass is giving an error as an undefined identifier.
Do pay attention to the build warning you get when you compile ConsoleApplication1:
warning MSB3214: "C:...\ConsoleApplication1\bin\Debug\ConsoleApplication1.dll" does not contain any types that can be registered for COM Interop.
That's not good of course. Also something you see with you look at the .tlb file with Oleview.exe's View + Typelib command. Or open the .tlh file that the #import directive generates with a text editor, find it back in the C++ project's Debug directory. You'll see that MyClass is completely missing, thus the compile error.
That is because of:
class MyClass : IMyClass
You forgot to declare it public. Required.
I have a standalone c# applications that does something specific (listens to TCP port and pronounces all strings that arrive to it via speech synthesizer). How can I make the c# class visible to a VBA program, same way other "References" are visible to it? I would appreciate short and clean example. I struggle to find one of those for some reason.
If there are some gotchas specific to c# <-> vba interaction, I would like to know about those too.
Here is a C# code. I build is as a class library with "Register for COM interop" setting.
When I add the resulting .tlb file to VBA references list, I expect to see SayCom library that has SayCom class with 2 methods, square and getCount. I do not see that. What am I missing?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
[assembly: CLSCompliant(true)]
namespace SayCom
{
[CLSCompliant(true)]
[ComVisible(true)]
public class SayCom
{
int count;
public SayCom()
{
count = 0;
}
[ComVisible(true)]
public int square(int x)
{
++count;
return x * x;
}
[ComVisible(true)]
public int getCount()
{
return count;
}
}
}
This works for me
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ClassLibrary1
{
[Guid("BBF87E31-77E2-46B6-8093-1689A144BFC6")]
[ComVisible(true)]
public interface MyMiniSubs
{
int square(int x);
int getCount();
}
[Guid("BBF87E31-77E2-46B6-8093-1689A144BFC7")]
[ClassInterface(ClassInterfaceType.None)]
public class Class1 : MyMiniSubs
{
int count;
public Class1()
{
count = 0;
}
[ComVisible(true)]
public int square(int x)
{
++count;
return x * x;
}
[ComVisible(true)]
public int getCount()
{
return count;
}
}
}
The only 'gotcha', as far as I know, is that your C# code needs to be CLS compliant. You should be able to follow the instructions here to import your C# code as a .dll into your VB application. Disclaimer: I have not tried this myself.
EDIT: Here's a more official MSDN reference that talks about calling functions from a .dll.
i have a .net dll which is written in c sharp, which uses linq to read data and return it to another calling vba app. i didn't plan for this so the initial project was written for it to be accessible by another .net app. so now i just found out that there's a lot of stuff about .net com interoperability and what not.
so i've learned that i need to user interface to make it work, and i need to regasm the dll to create a type library file which i can reference directly from the vba/vb6 app.
as of now i'm getting the problem of when i do this Dim obj As DtasApiTool.Program, it's fine but on the next line set obj = new DtasApiTool.Program will cause an error about New operator not being used properly. when i tested another .net dll from codeproject it works fine.
so my question is, what am i doing wrong here?
am i using too many references, as in
the using system.xxx?
or is it due
to some files that i have in the
projects, i.e. app.config
file, etc.
and how do i get the guid?
as i have very limited knowledge or experience in all of this ,i'm basing what is right or wrong from the example code in code project :( so feel free to comment on anything.
this is the code that i'm using:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.OleDb;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using System.IO;
//using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
//using System.Windows.Forms;
namespace DtasApiTool
{
[Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7059")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _Program
{
[DispId(1)]
string Get_All_Locales();
[DispId(2)]
string Get_All_Levels(string locale);
[DispId(3)]
string Get_Subjects_ByLocaleLevelId(string locale, int levelId);
[DispId(4)]
string Get_Topic_ByLevelIdLocaleSubjectId(int levelId, string locale, int subjectId);
[DispId(5)]
string Get_Subtopic_ByLevelIdLocaleSubjectIdTopicId(int levelId, string locale, int subjectId, int topicId);
[DispId(6)]
string Get_Skill_ByLevelIdLocaleSubjectIdTopicIdSubtopicId(int levelId, string locale, int subjectId, int topicId, int subtopicId);
[DispId(7)]
string Get_All_Subjects(string locale);
}
[Guid("09FE32AD-4BF8-495f-AB4D-6C61BD463EA4")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("DtasApiTool.Program")]
public class Program : _Program
{
...}
}
Hm - I'm using C# DLLs all the time with COM and never had problems. I'm not even using the interface-approach you have there. This is, for example, an anonymized part of a DLL I'm using in Microsoft Dynamics NAV via COM:
using ...;
namespace SomeCOMTool
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("MyCOMTool")]
[ComVisible(true)]
[Guid("your-guid-here without curly brackets!")]
public class MyCOMTool
{
/// <summary>
/// Empty constructor used by Navision to create a new instance of the control.
/// </summary>
public MyCOMTool()
{
}
[DispId(101)]
public bool DoSomething(string input, ref string output)
{
}
}
}
Of course "COM visible" is set in the assembly options and there's also a GUID in the respective field.