Gettings C7621 when trying to use C++ 20 modules - c++

I'm following this example of how to write modules in c++ 20: https://learn.microsoft.com/en-us/cpp/cpp/tutorial-named-modules-cpp?view=msvc-170 and I continue getting an error C7621 "module partition 'XXX' for module unit 'XXX' was not found.
Following the example I've created the next ixx *primary module interface:
export module Chapter01;
export import :Question01;
I've then added the ixx module partition file:
export module Chapter01:Question01;
import <iostream>;
import <set>;
using namespace std;
export bool IsUnique(const std::string& str);
And the cpp implementation file:
module Chapter01:Question01;
import <iostream>;
import <set>;
using namespace std;
bool IsUnique(const std::string& str)
{
set<char> charset = set<char>();
for (const char c : str)
{
if (charset. Contains(c))
{
return false;
}
charset. Insert(c);
}
return true;
}
And I keep getting a C7621: module partition 'Question01' for module unit 'Chapter01' was not found
Looking at the example over and over again I can't seem to find the difference.
Removing the cpp file entirely and putting the implementation in the ixx file fixes the issue, but I would still like to understand why the separation doesn't work.
P.S. What is the best practice when working with modules? To separate the ixx and cpp files or to just include ixx files?

The tutorial you're using is incorrect. It suggests that you can have an implementation partition and interface partition that use the same partition name in the same module.
This is not allowed. All partitions within the same module must have different partition names.
Furthermore, the only reason to have an implementation partition is if you want some other module unit to be able to import that partition. Most implementation partitions don't need to be imported. So your implementation unit should just use module Chapter01;, and it will automatically import the Chapter01 module.

Related

Using Metaclasses for self-registering plugins? (Approach help)

I'm trying to write a Python (2.7) library which loads certain classes at runtime. These classes contain a predefined set of methods.
My approach is to define a few Metaclasses which I work with in my library. I would for example define a "Navigation" Metaclass and work with it in the library. Then someone could write a class "Mainmenu" which contains some type of type definition that it is a "Navigation" plugin. And then the Library could use this class.
I am able to load modules and I'm able to write Metaclasses. My problem lies in combining these two things.
First there is the problem that I want the "plugin-classes" to be in a different (configurable) folder. So I can not do:
__metaclass__ = Navigation
because the Navigation class is part of my library and won't be there in the plugin-folder...
How could I solve the Problem of telling the type that the plugin is for? (Navigation, content.... e.g)
EDIT2: I solved the following problem. I found out that I can just ask the module to give me a dict.
My first problem still exists though
EDIT:
I managed registering and loading "normal" classes with a registry up until the following point:
from os import listdir
from os.path import isfile, join
import imp
class State:
registry = {}
def register_class(self,target_class):
self.registry[target_class.__name__] = target_class
print target_class.__name__+" registered!"
def create(self,classname):
tcls = self.registry[classname]
print self.registry[classname]
return tcls()
s = State()
mypath = """C:\metatest\plugins"""
files = [f for f in listdir(mypath) if isfile(join(mypath, f))]
for f in files:
spl = f.split(".")
if spl[1] == "py":
a = imp.load_source(spl[0], mypath + """\\""" + f)
s.register_class(a)
The problem I have at the end now is, that "a" is the loaded module, so it is a module-object. In my case there is only one class in it.
How can I get a Class object from the loaded module, so I can register the class properly??
So - let's check your problem steping back on your current proposal.
You need a way to have plug-ins for a larger system - the larger system won't know about the plug-ins at coding time - but the converse is not true: your plugins should be able to load modules, import base classes and call functions on your larger system.
Unless you really have something so plugable that plug-ins can work with more than one larger system. I doubt so, but if that is the case you need a framework that can register interfaces and retrieve classes and adapter-implementations between different classes. That framework is Zope Interface - you should read the documentation on it here: https://zopeinterface.readthedocs.io/en/latest/
Much more down to earth will be a plug-in system that sacans some preset directories for Python files and import those. As I said above, there is no problem if these files do import base classes (or metaclasses, for the record) on your main system: these are already imported by Python in the running process anyway, their import in the plug-in will just make then show up as available on the plug-in code.
You can use the exact code above, just add a short metaclass to register derived classes from State - you can maketeh convention that each base class for a different plug-in category have the registry attribute:
class RegistryMeta(type):
def __init__(cls, name, bases, namespace):
for base in cls.__mro__:
if 'registry' in base.__dict__:
if cls.__name__ in base.registry:
raise ValueError("Attempting to registrate plug-in with the name {} which is already taken".format(cls.__name__))
base.registry[cls.__name__] = cls
break
super(RegistryMeta, cls).__init__(name, base, namespace)
class State(object):
__metaclass__ = RegistryMeta
registry = {}
...
(keep the code for scanning the directory and loading modules - just switch all directory separation bars to "/" - you still are not doing it right and is subject to surprises by using "\")
and on the plug-in code include:
from mysystem import State
class YourClassCode(State):
...
And finally, as I said in the comment : you should really check the possibility of using Python 3.6 for that. Among other niceties, you could use the __init_subclass__ special method instead of needing a custom metaclass for keeping your registries.

How do you compile multiple files in different folders in D?

project
---|source
------ |controllers
-------|models
-------|lib
----------|field.d
-------|app.d
I run dub but I get this error:
Error: module field from file ... conflicts with another module field from
file source/lib/field.d
field.d looks like this:
module field;
class Field(T){
this(T def_val,bool required,string help_text);
bool validate();
private bool _validate();
}
Always put a module statement in any file that is going to be imported, and use a package name consistently as well to avoid conflicts.
So, instead of calling it simply module field;, call it module myapplication.field;, or even module myapplication.lib.field;, and of course, also import it by the same full name when you use it.
I'm not sure if dub will just work like that though (I don't use it personally), but the language lets you give a module any name, even if it doesn't match the filename, which helps in situations like this, avoiding name conflicts.
In general, if you give them all full, unique names, then compile them all at once: dmd app.d lib/field.d [and any other files your project has], things will just work.

Accessing c++ class from python

I have a big c++ program in a single .cpp file which defines a lot of classes(interdependent of each other) and finally runs a main function. Now I am interested only in using one of this classes in python, specifically one method of this class which accepts 5 floats as inputs and outputs one float. I am trying to find the simplest method to achieve this. After not having success with boost:python(mainly because of installation issues) I have come to Cython which in the current version supports C++. I could successfully run the Rectangle example given in the Cython tutorial but I can't get how to proceed and adapt this to my case where I don't need a so complicated .pyx file, and where I don't have a .h file. Can somebody explain me in simple words what should I write in setup.py and in the .pyx file if my .cpp file has for example the structure:
...
class Nuclei {
public:
...
double potential(float,float,float,float,float);
...
private:
...
};
...
If all you are looking to do is call a single function, Extending Python With C/C++ is probably the simplest approach. This page provides a good example.
The relevant setup.py code in that example is
from distutils.core import setup, Extension
module1 = Extension('demo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include'],
libraries = ['tcl83'],
library_dirs = ['/usr/local/lib'],
sources = ['demo.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
author = 'Martin v. Loewis',
author_email = 'martin#v.loewis.de',
url = 'http://docs.python.org/extending/building',
long_description = '''
This is really just a demo package.
''',
ext_modules = [module1])
If the C++ code you want to call is in demo.c, it could be used with import demo in Python.
Note that it is not nearly that simple- you'll be creating a function that takes a PyObject * with arguments and returns a PyObject *, and a lot can be said about how those are constructed. Take a look at the pages linked to above- they are filled with examples.

Boost::Python: embed and load Boost::Python modules and converters

This might be a trivial one, but I kind of stuck here.
I have the following setup:
entity.cpp/.hpp: containing my Entity class definition and implementation.
entity_wrap.cpp: my boost python wrapper file which I compile to entity.so
entity_test.cpp: a test file
What I'd like to do in entity_test.cpp is the following:
Py_SetProgramName(argv[0]);
Py_Initialize();
...
Entity* entity = new Entity;
globals["entity"] = entity;
I now get the following exception:
TypeError: No to_python (by-value) converter found for C++ type: Entity
Which is obvious since I do not load the conversion definition of my types. I now tried to load the entity.so with globals["entity_module"] = import("entity"); but I ran into this exception:
ImportError: No module named entity
I can load the module from a python shell as expected.
My question now is: how do I load the converters defined in entity_wrap.cpp?
Solution
As eudoxos stated, I have to ensure that the module I want to load is in the sys.path:
globals["sys"] = import("sys");
exec("sys.path.append('/path/to/my/module')\n"
"import entity", globals);
It now works like a charm. Apparently just using Py_SetProgramName(argv[0]); was not enough.
With boost::python::import; watch for sys.path though so that your module is found, you might want to add a call to
PyRun_SimpleString("import sys; sys.path.append('.');")
first. Well, you can do the import via PyRun_SimpleString as well then :-)
Another option: write the entity_test itself in python.

Python SIP expose function

I'm writing a Python module for some C++ code using SIP. However whilst I can easily expose classes, I cannot find a way to expose standalone functions.
Here is my header file defining the functions that I wish to expose to Python: ProxySettings.h
#include <Windows.h>
#include <Wininet.h>
bool SetConnectionOptions(const char * proxy_full_addr);
bool DisableConnectionProxy();
And here is my attempt at my SIP file so far: ProxySettings.sip. Currently running sip.exe generates C++ code with no problems, but when I come to compile it, the compiler complains about missing identifiers SetConnectionOptions and DisableConnectionProxy.
%Module ieproxy 0
bool SetConnectionOptions(const char * proxy_full_addr);
bool DisableConnectionProxy();
I think that I have to use a directive to include the ProxySettings.h header file into my SIP file, but I am not sure what directive to use. %TypeHeaderCode which is what you use for a class doesn't work with just a function.
Does anyone have any suggestions?
Try this:
%Module ieproxy 0
%UnitCode
#include <ProxySettings.h>
%End
bool SetConnectionOptions(const char * proxy_full_addr);
bool DisableConnectionProxy();