What is a correct way to obtain FOnlineSubsystemSteam instance in c++ code - unreal-engine4

I'm trying to get steam app id and steam user id in my Unreal Engine 4 project in the following way:
if (SteamAPI_Init())
{
IOnlineSubsystem* ossBase = IOnlineSubsystem::Get();
FOnlineSubsystemSteam* oss = Cast<FOnlineSubsystemSteam*>(ossBase);
if (!oss) {
printText(TEXT("Steam Subsystem is down!"), FColor::Red.WithAlpha(255));
return;
}
auto SteamID = FString(std::to_string(SteamUser()->GetSteamID().ConvertToUint64()).c_str());
auto AppID = FString(std::to_string(oss->GetSteamAppId()).c_str());
But it is not possible to convert IOnlineSubsystem to FOnlineSubsystemSteam. So what is a correct way to obtain the instance of FOnlineSubsystemSteam?

The solution is to use static_cast:
FOnlineSubsystemSteam* oss = static_cast<FOnlineSubsystemSteam*>(ossBase);
This one works. It seems obvious to use UE4 Cast, but in this case it does not work.

Related

How to use named object in macOS to limit app instances?

I need to preface this by saying that I'm coming from years of developing on Windows. This time I'm developing the UI for my macOS app using SwiftUI. The goal is to allow only one instance of the app, depending on where it's started from. For instance, if you copy the app into:
/Users/me/Documents/MyAppCopy/MyApp.app
and to:
/Users/me/Documents/MyApp.app
There should be only two instances of the app allowed, each from those respective locations.
On Windows I would use a named kernel object, say a named event, create it when the app starts and see if it already existed. If so, I will quit the app. Then when the first instance of the app closes, the named event is destroyed by the system automatically.
So I thought to try the same on macOS, but evidently Linux/BSD treats named objects differently.
If I do get the name of the object by calling:
var objName : Bundle.main.bundlePath
IsAnotherInstanceRunning(objName, objName.lengthOfBytes(using: String.Encoding.utf8))
and then using C, remove slashes from it, and use it in a named semaphore:
bool IsAnotherInstanceRunning(const char* pBundlePath, size_t szcbLnPath)
{
bool bResult = false;
char* pName = (char*)malloc(szcbLnPath + 1);
if(pName)
{
memcpy(pName, pBundlePath, szcbLnPath);
pName[szcbLnPath] = 0;
//Remove slashes
int cFnd = '/';
char *cp = strchr(pName, cFnd);
while (cp)
{
*cp = '_';
cp = strchr(cp, cFnd);
}
//Create if doesn't exist, and return an error if it exists
sem_t *sem = sem_open(pName, O_CREAT | O_EXCL, 0644, 0);
if(sem == SEM_FAILED)
{
//Failed, see why
int nErr = errno;
if(nErr == EEXIST)
{
//Already have it
bResult = true;
}
}
free(pName);
}
return bResult;
}
Assuming that the path name isn't too long (this is an issue, but it is irrelevant to this question) - the approach above works, but it has one downside.
If I don't close and remove the name semaphore with:
sem_close(sem);
sem_unlink(pName);
It stays in the system if the instance of my app crashes. Which creates an obvious problem for the code above.
So how would you do this on Linux/macOS?
To prevent/abort the start of an app while another instance is running, you can also use high-level AppKit stuff (we do this in one of our apps and it works reliably).
Use NSWorkspace.runningApplications to get a list of, well, the currently running applications. Check this list, and filter it for the bundleIdentifier of your app. You can then also check the bundleURL to decide whether it's OK to start the current app, which seems to be what you want to do. See also NSRunningApplication.current to get the informations about your current process.
(You can do [otherRunningApplication isEqual:NSRunningApplication.current] to check/filter the current process.)
Do this check in your applicationWillFinishLaunching or applicationDidFinishLaunching method.

How to set the proper data type when writing to an OPC-UA node in Milo?

I am an OPC-UA newbie integrating a non-OPC-UA system to an OPC-UA server using the Milo stack. Part of this includes writing values to Nodes in the OPC-UA server. One of my problems is that values from the other system comes in the form of a Java String and thus needs to be converted to the Node's proper data type. My first brute force proof-of-concept uses the below code in order to create a Variant that I can use to write to the Node (as in the WriteExample.java). The variable value is the Java String containing the data to write, e.g. "123" for an Integer or "32.3" for a Double. The solution now includes hard-coding the "types" from the Identifiers class (org.eclipse.milo.opcua.stack.core, see the switch statement) which is not pretty and I am sure there is a better way to do this?
Also, how do I proceed if I want to convert and write "123" to a node that is, for example,
UInt64?
try {
VariableNode node = client.getAddressSpace().createVariableNode(nodeId);
Object val = new Object();
Object identifier = node.getDataType().get().getIdentifier();
UInteger id = UInteger.valueOf(0);
if(identifier instanceof UInteger) {
id = (UInteger) identifier;
}
System.out.println("getIdentifier: " + node.getDataType().get().getIdentifier());
switch (id.intValue()) {
// Based on the Identifiers class in org.eclipse.milo.opcua.stack.core;
case 11: // Double
val = Double.valueOf(value);
break;
case 6: //Int32
val = Integer.valueOf(value);
break;
}
DataValue data = new DataValue(new Variant(val),StatusCode.GOOD, null);
StatusCode status = client.writeValue(nodeId, data).get();
System.out.println("Wrote DataValue: " + data + " status: " + status);
returnString = status.toString();
} catch (Exception e) {
System.out.println("ERROR: " + e.toString());
}
I've looked at Kevin's response to this thread: How do I reliably write to a OPC UA server? But I'm still a bit lost... Some small code example would really be helpful.
You're not that far off. Every sizable codebase eventually has one or more "TypeUtilities" classes, and you're going to need one here.
There's no getting around that fact that you need to be able to map types in your system to OPC UA types and vice versa.
For unsigned types you'll use the UShort, UInteger, and ULong classes from the org.eclipse.milo.opcua.stack.core.types.builtin.unsigned package. There are convenient static factory methods that make their use a little less verbose:
UShort us = ushort(foo);
UInteger ui = uint(foo);
ULong ul = ulong(foo);
I'll explore that idea of including some kind of type conversion utility for an upcoming release, but even with that, the way OPC UA works you have to know the DataType of a Node to write to it, and in most cases you want to know the ValueRank and ArrayDimensions as well.
You either know these attribute values a priori, obtain them via some other out of band mechanism, or you read them from the server.

mini filter driver | passing information from pre-operation to post-operation

I'm tracking changed made to file and would like to "remember" and pass some information from the pre-operation callback to the post-operation callback.
What is the best way to do it?
[Edit: The driver should only support Windows 10 everything else is a bonus]
You can simply use the PVOID *CompletionContext in PreOperation to store a pointer to the data you want to pass to the PostOperation.
In the PostOperation just use CompletionContext as it will be the data you pointed it to in the PreOperation.
For example:
PreOp:
MyPreOpData = ExAllocatePoolWithTag(DATA_SIZE);
FltGetFileNameInformation(&NameInfo);
MyPreData->NameInfo = NameInfo;
MyPreData->OtherData = MyDrvGetOtherData(Params);
*CompletionContext = MyPreData;
PostOp:
if (CompletionContext != NULL)
{
PMY_DATA MyPreData = (PMY_DATA)CompletionContext;
// now continue using the data queried in the PreOp
...
// when done free it
ExFreePoolWithTag(MyPreData);
}
See here for more details.
Good luck,
Gabriel

How to get the current tool SitePage and/or its Properties?

With the ToolManager I can get the the current placement, the context and of course, the Site through the SiteService. But I want to get the current SitePage properties the user is currently accessing.
This doubt can be extended to the current Tool properties with a
little more emphasis considering that once I have the Tool I could not
find any methods covering the its properties.
I could get the tool properties and I'm using it (it is by instance) through Properties got with sitepage.getTool(TOOLID).getConfig(). To save a property, I'm using the ToolConfiguration approach and saving the data after editing with the ToolConfiguration.save() method. Is it the correct approach?
You can do this by getting the current tool session and then working your way backward from that. Here is a method that should do it.
public SitePage findCurrentPage() {
SitePage sp = null;
ToolSession ts = SessionManager.getCurrentToolSession();
if (ts != null) {
ToolConfiguration tool = SiteService.findTool(ts.getPlacementId());
if (tool != null) {
String sitePageId = tool.getPageId();
sp = s.getPage(sitePageId);
}
}
return sp;
}
Alternatively, you could use the current tool to work your way to it but I think this method is harder.
String toolId = toolManager.getCurrentTool().getId();
String context = toolManager.getCurrentPlacement().getContext();
Site s = siteService.getSite( context );
ToolConfiguration tc = s.getTool(toolId);
String sitePageId = tc.getPageId();
SitePage sp = s.getPage(sitePageId);
NOTE: I have not tested this code to make sure it works.

Call TYPO3 plugin from other plugin's body

I need to call typo3 plugin from other plugin's body and pass its result to template. This is pseudo-code that describes what I want to achieve doing this:
$data['###SOME_VARIABLE###'] = $someOtherPlugin->main();
$this->cObj->substituteMarkerArray($someTemplate, $data);
Is it possible?
Thanks!
It doenst work if you use the whole pi construct, e.g. for links, marker function etc, and the TSFE Data can be corrupted.
Dmitry said:
http://lists.typo3.org/pipermail/typo3-english/2008-August/052259.html
$cObjType = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_rgsmoothgallery_pi1'];
$conf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_rgsmoothgallery_pi1.'];
$cObj = t3lib_div::makeInstance('tslib_cObj');
$cObj->start(array(), '_NO_TABLE');
$conf['val'] = 1;
$content = $cObj->cObjGetSingle($cObjType, $conf); //calling the main method
You should use t3lib_div:makeInstance method.
There is a working example from TYPO3's "powermail" extension.
function getGeo() {
// use geo ip if loaded
if (t3lib_extMgm::isLoaded('geoip')) {
require_once( t3lib_extMgm::extPath('geoip').'/pi1/class.tx_geoip_pi1.php');
$this->media = t3lib_div::makeInstance('tx_geoip_pi1');
if ($this->conf['geoip.']['file']) { // only if file for geoip is set
$this->media->init($this->conf['geoip.']['file']); // Initialize the geoip Ext
$this->GEOinfos = $this->media->getGeoIP($this->ipOverride ? $this->ipOverride : t3lib_div::getIndpEnv('REMOTE_ADDR')); // get all the infos of current user ip
}
}
}
The answer of #mitchiru is nice and basically correct.
If you have created your outer extension with Kickstarter and you are using pi_base then there is already an instance of tslib_cObj and the whole construct becomes simpler:
// get type of inner extension, eg. USER or USER_INT
$cObjType = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_innerextension_pi1'];
// get configuration array of inner extension
$cObjConf = $GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_innerextension_pi1.'];
// add own parameters to configuration array if needed - otherwise skip this line
$cObjConf['myparam'] = 'myvalue';
// call main method of inner extension, using cObj of outer extension
$content = $this->cObj->cObjGetSingle($cObjType, $cObjConf);
Firstly, you have to include your plugin class, before using, or outside your class:
include_once(t3lib_extMgm::extPath('myext').'pi1/class.tx_myext_pi1.php');
Secondly in your code (in the main as example)
$res = tx_myext_pi1::myMethod();
This will work for sure (I've checked this): http://lists.typo3.org/pipermail/typo3-english/2008-August/052259.html.
Probably Fedir's answer is correct too but I didn't have a chance to try it.
Cheers!